This commit is contained in:
Nick Bebout 2011-03-12 02:44:15 +00:00
parent ec6a0c4d01
commit e0fc454e0d
7 changed files with 105 additions and 74 deletions

View file

@ -1,5 +1,8 @@
#!/bin/cat #!/bin/cat
Costa Tsaousis
Had a problem with a huge mailbox (20000 messages)
Scott Glenn Scott Glenn
Found the bug about --regexmess applied only on the first Found the bug about --regexmess applied only on the first
message. message.

View file

@ -1,15 +1,27 @@
RCS file: RCS/imapsync,v RCS file: RCS/imapsync,v
Working file: imapsync Working file: imapsync
head: 1.129 head: 1.132
branch: branch:
locks: strict locks: strict
access list: access list:
symbolic names: symbolic names:
keyword substitution: kv keyword substitution: kv
total revisions: 129; selected revisions: 129 total revisions: 132; selected revisions: 132
description: description:
---------------------------- ----------------------------
revision 1.132
date: 2005/05/20 03:18:48; author: gilles; state: Exp; lines: +23 -16
Updated doc with all options.
----------------------------
revision 1.131
date: 2005/05/20 02:47:56; author: gilles; state: Exp; lines: +5 -37
Removed unused code
----------------------------
revision 1.130
date: 2005/05/20 02:40:26; author: gilles; state: Exp; lines: +23 -15
Added --useheader option
----------------------------
revision 1.129 revision 1.129
date: 2005/05/19 01:54:31; author: gilles; state: Exp; lines: +14 -11 date: 2005/05/19 01:54:31; author: gilles; state: Exp; lines: +14 -11
Added --buffersize option. Added --buffersize option.

20
README
View file

@ -2,7 +2,7 @@ NAME
imapsync - IMAP synchronization, copy or migration tool. Synchronize imapsync - IMAP synchronization, copy or migration tool. Synchronize
mailboxes between two imap servers. Good at IMAP migration. mailboxes between two imap servers. Good at IMAP migration.
$Revision: 1.129 $ $Revision: 1.132 $
INSTALL INSTALL
imapsync works fine under any Unix OS. imapsync works fine under any Unix OS.
@ -29,25 +29,31 @@ SYNOPSIS
imapsync imapsync
imapsync [--host1 server1] [--port1 <num>] imapsync [--host1 server1] [--port1 <num>]
[--user1 <string>] [--passfile1 <string>] [--user1 <string>] [--passfile1 <string>]
[--host2 server2] [--port2 <num>] [--host2 server2] [--port2 <num>]
[--user2 <string>] [--passfile2 <string>] [--user2 <string>] [--passfile2 <string>]
[--noauthmd5]
[--folder <string> --folder <string> ...] [--folder <string> --folder <string> ...]
[--include <regex>] [--exclude <regex>] [--include <regex>] [--exclude <regex>]
[--prefix2 <string>] [--prefix2 <string>] [--regextrans2 <regex>]
[--sep1 <char>] [--sep1 <char>]
[--sep2 <char>] [--sep2 <char>]
[--justfolders] [--justconnect]
[--syncinternaldates] [--syncinternaldates]
[--buffersize <int>]
[--syncacls]
[--regexmess <regex>] [--regexmess <regex>]
[--maxsize <int>] [--maxsize <int>]
[--maxage <int>] [--maxage <int>]
[--skipheader <regex>] [--skipheader <regex>]
[--useheader <string>] [--useheader <string>]
[--skipsize] [--skipsize]
[--delete] [--expunge] [--delete] [--expunge]
[--subscribed] [--subscribe] [--subscribed] [--subscribe]
[--foldersizes] [--nofoldersizes]
[--dry] [--dry]
[--debug] [--debugimap] [--debug] [--debugimap]
[--timeout <int>] [--timeout <int>] [--fast]
[--version] [--help] [--version] [--help]
DESCRIPTION DESCRIPTION
@ -247,5 +253,5 @@ AUTHOR
teaching free open and gratis softwares. Don't hesitate to pay him for teaching free open and gratis softwares. Don't hesitate to pay him for
that services. that services.
$Id: imapsync,v 1.129 2005/05/19 01:54:31 gilles Exp $ $Id: imapsync,v 1.132 2005/05/20 03:18:48 gilles Exp $

10
TODO
View file

@ -1,9 +1,10 @@
TODO file for imapsync TODO file for imapsync
---------------------- ----------------------
Look at http://barnson.org/node/81
Update doc with ALL options. Interface with external software like procmail
Look at http://barnson.org/node/81
Add in doc: Add in doc:
> The problem seems to be that one of the imap servers (the destination > The problem seems to be that one of the imap servers (the destination
@ -48,7 +49,6 @@ Look at http://freshmeat.net/projects/freshmeat-submit/
Look at comp.mail.imap http://groups.google.fr/groups?q=imapsync Look at comp.mail.imap http://groups.google.fr/groups?q=imapsync
Think about speed.
Explain expunge behavior Explain expunge behavior
@ -56,6 +56,10 @@ Add a --recurse option when --folder option is used.
Add --prefix1 option. Don't know what is the need exactly. Add --prefix1 option. Don't know what is the need exactly.
DONE. Update doc with ALL options.
DONE. Think about speed.
DONE. Pb if "to separator" is in "from folder" name. DONE. Pb if "to separator" is in "from folder" name.
Have to choose a caracter != to separator and Have to choose a caracter != to separator and
not in from folders. The solution can be to not in from folders. The solution can be to

View file

@ -1 +1 @@
1.129 1.132

View file

@ -6,7 +6,7 @@ imapsync - IMAP synchronization, copy or migration
tool. Synchronize mailboxes between two imap servers. Good tool. Synchronize mailboxes between two imap servers. Good
at IMAP migration. at IMAP migration.
$Revision: 1.129 $ $Revision: 1.132 $
=head1 INSTALL =head1 INSTALL
@ -35,25 +35,31 @@ $Revision: 1.129 $
imapsync imapsync
imapsync [--host1 server1] [--port1 <num>] imapsync [--host1 server1] [--port1 <num>]
[--user1 <string>] [--passfile1 <string>] [--user1 <string>] [--passfile1 <string>]
[--host2 server2] [--port2 <num>] [--host2 server2] [--port2 <num>]
[--user2 <string>] [--passfile2 <string>] [--user2 <string>] [--passfile2 <string>]
[--noauthmd5]
[--folder <string> --folder <string> ...] [--folder <string> --folder <string> ...]
[--include <regex>] [--exclude <regex>] [--include <regex>] [--exclude <regex>]
[--prefix2 <string>] [--prefix2 <string>] [--regextrans2 <regex>]
[--sep1 <char>] [--sep1 <char>]
[--sep2 <char>] [--sep2 <char>]
[--justfolders] [--justconnect]
[--syncinternaldates] [--syncinternaldates]
[--maxsize <int>] [--buffersize <int>]
[--maxage <int>] [--syncacls]
[--regexmess <regex>] [--regexmess <regex>]
[--maxsize <int>]
[--maxage <int>]
[--skipheader <regex>] [--skipheader <regex>]
[--useheader <string>] [--useheader <string>]
[--skipsize] [--skipsize]
[--delete] [--expunge] [--delete] [--expunge]
[--subscribed] [--subscribe] [--subscribed] [--subscribe]
[--foldersizes] [--nofoldersizes]
[--dry] [--dry]
[--debug] [--debugimap] [--debug] [--debugimap]
[--timeout <int>] [--timeout <int>] [--fast]
[--version] [--help] [--version] [--help]
=cut =cut
@ -289,7 +295,7 @@ Gilles LAMIRAL earn his living writing, installing,
configuring and teaching free open and gratis configuring and teaching free open and gratis
softwares. Don't hesitate to pay him for that services. softwares. Don't hesitate to pay him for that services.
$Id: imapsync,v 1.129 2005/05/19 01:54:31 gilles Exp $ $Id: imapsync,v 1.132 2005/05/20 03:18:48 gilles Exp $
=cut =cut
@ -313,7 +319,8 @@ my(
$sep1, $sep2, $sep1, $sep2,
$syncinternaldates, $syncacls, $syncinternaldates, $syncacls,
$maxsize, $maxage, $maxsize, $maxage,
$skipheader, $skipsize, $foldersizes, $buffersize, $skipheader, @useheader,
$skipsize, $foldersizes, $buffersize,
$delete, $expunge, $dry, $delete, $expunge, $dry,
$authmd5, $authmd5,
$subscribed, $subscribe, $subscribed, $subscribe,
@ -333,7 +340,7 @@ my(
use vars qw ($opt_G); # missing code for this will be option. use vars qw ($opt_G); # missing code for this will be option.
$rcs = ' $Id: imapsync,v 1.129 2005/05/19 01:54:31 gilles Exp $ '; $rcs = ' $Id: imapsync,v 1.132 2005/05/20 03:18:48 gilles Exp $ ';
$rcs =~ m/,v (\d+\.\d+)/; $rcs =~ m/,v (\d+\.\d+)/;
$VERSION = ($1) ? $1 : "UNKNOWN"; $VERSION = ($1) ? $1 : "UNKNOWN";
@ -370,8 +377,8 @@ $error=0;
my $banner = join("", my $banner = join("",
'$RCSfile: imapsync,v $ ', '$RCSfile: imapsync,v $ ',
'$Revision: 1.129 $ ', '$Revision: 1.132 $ ',
'$Date: 2005/05/19 01:54:31 $ ', '$Date: 2005/05/20 03:18:48 $ ',
"\n", "\n",
"Mail::IMAPClient version used here is ", "Mail::IMAPClient version used here is ",
$VERSION_IMAPClient, " auth md5 : $md5_supported", $VERSION_IMAPClient, " auth md5 : $md5_supported",
@ -404,6 +411,8 @@ $authmd5 = (defined($authmd5)) ? $authmd5 : 1;
$syncacls = (defined($syncacls)) ? $syncacls : 0; $syncacls = (defined($syncacls)) ? $syncacls : 0;
$foldersizes = (defined($foldersizes)) ? $foldersizes : 1; $foldersizes = (defined($foldersizes)) ? $foldersizes : 1;
@useheader = ("ALL") unless (@useheader);
print "From imap server [$host1] port [$port1] user [$user1]\n"; print "From imap server [$host1] port [$port1] user [$user1]\n";
print "To imap server [$host2] port [$port2] user [$user2]\n"; print "To imap server [$host2] port [$port2] user [$user2]\n";
@ -444,6 +453,11 @@ $from = login_imap($host1, $port1, $user1, $password1, $debugimap, $timeout);
$debugimap and print "To connection\n"; $debugimap and print "To connection\n";
$to = login_imap($host2, $port2, $user2, $password2, $debugimap, $timeout); $to = login_imap($host2, $port2, $user2, $password2, $debugimap, $timeout);
# No history
$from->Clear(1);
$to->Clear(1);
sub login_imap { sub login_imap {
my($host, $port, $user, $password, my($host, $port, $user, $password,
$debugimap, $timeout, $authmech) = @_; $debugimap, $timeout, $authmech) = @_;
@ -745,21 +759,16 @@ FOLDER: foreach my $f_fold (@f_folders) {
my %f_hash = (); my %f_hash = ();
my %t_hash = (); my %t_hash = ();
# No history
$from->Clear(1);
$to->Clear(1);
print "From Buffer I/O : ", $from->Buffer(), "\n"; print "From Buffer I/O : ", $from->Buffer(), "\n";
print "To Buffer I/O : ", $to->Buffer(), "\n"; print "To Buffer I/O : ", $to->Buffer(), "\n";
# $from->Buffer(4096*64);
# $to->Buffer(4096*64);
# print "From Buffer I/O : ", $from->Buffer(), "\n";
# print "To Buffer I/O : ", $to->Buffer(), "\n";
print "++++ From Parse 1 ++++\n"; print "++++ From Parse 1 ++++\n";
my $f_heads = $from->parse_headers([@f_msgs],"ALL") if (@f_msgs) ; my $f_heads = $from->parse_headers($from->Range([@f_msgs]),@useheader)
if (@f_msgs) ;
print "Time headers: ", timenext(), " s\n"; print "Time headers: ", timenext(), " s\n";
my $f_size = $from->fetch_hash("RFC822.SIZE") if (@f_msgs); my $f_size = $from->fetch_hash("RFC822.SIZE") if (@f_msgs);
print "Time sizes : ", timenext(), " s\n"; print "Time sizes : ", timenext(), " s\n";
@ -776,7 +785,8 @@ FOLDER: foreach my $f_fold (@f_folders) {
print "Time headers: ", timenext(), " s\n"; print "Time headers: ", timenext(), " s\n";
print "\n++++ To Parse 1 ++++\n"; print "\n++++ To Parse 1 ++++\n";
my $t_heads = $to->parse_headers([@t_msgs],"ALL") if (@t_msgs); my $t_heads = $to->parse_headers($to->Range([@t_msgs]),@useheader)
if (@t_msgs);
print "Time headers: ", timenext(), " s\n"; print "Time headers: ", timenext(), " s\n";
my $t_size = $to->fetch_hash("RFC822.SIZE") if (@t_msgs); my $t_size = $to->fetch_hash("RFC822.SIZE") if (@t_msgs);
print "Time sizes : ", timenext(), " s\n"; print "Time sizes : ", timenext(), " s\n";
@ -993,6 +1003,7 @@ sub get_options
"help" => \$help, "help" => \$help,
"timeout=i" => \$timeout, "timeout=i" => \$timeout,
"skipheader=s" => \$skipheader, "skipheader=s" => \$skipheader,
"useheader=s" => \@useheader,
"skipsize!" => \$skipsize, "skipsize!" => \$skipsize,
); );
@ -1030,7 +1041,7 @@ sub parse_header_msg1 {
$debug and print "${s}H $h:", $val, "\n"; $debug and print "${s}H $h:", $val, "\n";
if ($skipheader and $h =~ m/$skipheader/) { if ($skipheader and $h =~ m/$skipheader/) {
$debug and print "Skipping header $h\n"; $debug and print "Skipping header $h\n";
next; next;
} }
$headstr .= "$h:". $val; $headstr .= "$h:". $val;
} }
@ -1047,38 +1058,6 @@ sub parse_header_msg1 {
$s_hash->{"$m_md5:$size"}{'m'} = $m_uid; $s_hash->{"$m_md5:$size"}{'m'} = $m_uid;
} }
sub parse_header_msg {
my ($m, $imap, $s, $s_hash) = @_;
$debug and print "-" x 50, "\nMSG $m\n";
my $head = $imap->parse_headers($m,"ALL");
my $headstr;
$debug and print "Head NUM:", scalar(keys(%$head)), "\n";
# no header -> return
return unless(scalar(keys(%$head)));
foreach my $h (sort keys(%$head)){
foreach my $val (sort @{$head->{$h}}) {
# no 8-bit data in headers !
$val =~ s/[\x80-\xff]/X/g;
# remove the first blanks (dbmail bug ?)
$val =~ s/^\s+//;
# show stuff in debug mode
$debug and print "${s}H $h:", $val, "\n";
if ($skipheader and $h =~ m/$skipheader/) {
$debug and print "Skipping header $h\n";
next;
}
$headstr .= "$h:". $val;
}
}
my $m_md5 = md5_base64($headstr);
my $size = $imap->size($m);
$debug and print "$s msg $m:$m_md5:$size\n";
$size = 0 if ($skipsize);
$s_hash->{"$m_md5:$size"}{'5'} = "$m_md5:$size";
$s_hash->{"$m_md5:$size"}{'s'} = $size;
$s_hash->{"$m_md5:$size"}{'m'} = $m;
}
sub firstline { sub firstline {
# extract the first line of a file (without \n) # extract the first line of a file (without \n)
@ -1110,7 +1089,8 @@ Several options are mandatory.
--user2 <string> : user to login. Mandatory. --user2 <string> : user to login. Mandatory.
--password2 <string> : password for the user2. Dangerous, use --passfile2 --password2 <string> : password for the user2. Dangerous, use --passfile2
--passfile2 <string> : password file for the user2. Contains the password. --passfile2 <string> : password file for the user2. Contains the password.
--noauthmd5 : don't use MD5 authentification --noauthmd5 : don't use MD5 authentification.
--authmd5 : use MD5 authentification.
--folder <string> : sync only this folder. --folder <string> : sync only this folder.
--folder <string> : and this one. --folder <string> : and this one.
--folder <string> : and this one, etc. --folder <string> : and this one, etc.
@ -1148,6 +1128,9 @@ Several options are mandatory.
final stats (skipped) don't count older messages final stats (skipped) don't count older messages
--skipheader <regex> : Don't take into account header keyword --skipheader <regex> : Don't take into account header keyword
matching <string> ex: --skipheader 'X.*' matching <string> ex: --skipheader 'X.*'
--useheader <string> : Use this header to compare messages on both sides.
Ex: Message-ID or Subject or Date.
--useheader <string> and this one, etc.
--skipsize : Don't take message size into account. --skipsize : Don't take message size into account.
--dry : do nothing, just print what would be done. --dry : do nothing, just print what would be done.
--subscribed : transfer only subscribed folders. --subscribed : transfer only subscribed folders.
@ -1162,7 +1145,7 @@ Several options are mandatory.
--debug : debug mode. --debug : debug mode.
--debugimap : imap debug mode. --debugimap : imap debug mode.
--version : print sotfware version. --version : print sotfware version.
--justconnect : just connect to both servers and print useful --justconnect : just connect to both servers and print useful
information. information.
--justfolders : just do things about folders (ignore messages). --justfolders : just do things about folders (ignore messages).
--fast : be faster. --fast : be faster.

View file

@ -1,6 +1,6 @@
#!/bin/sh #!/bin/sh
# $Id: tests.sh,v 1.37 2005/05/19 01:50:02 gilles Exp $ # $Id: tests.sh,v 1.38 2005/05/20 02:51:33 gilles Exp $
#### Shell pragmas #### Shell pragmas
@ -476,7 +476,8 @@ big_transfert()
--host2 plume --user2 tete@est.belle \ --host2 plume --user2 tete@est.belle \
--passfile2 /var/tmp/secret.tete \ --passfile2 /var/tmp/secret.tete \
--subscribed --foldersizes --noauthmd5 \ --subscribed --foldersizes --noauthmd5 \
--fast --folder INBOX.Backup || \ --fast --folder INBOX.Backup \
--useheader Message-ID --useheader Received || \
true true
} }
date2=`date` date2=`date`
@ -576,6 +577,27 @@ essnet_plume2()
--prefix2 INBOX. --regextrans2 's¤INBOX.INBOX¤INBOX¤' --prefix2 INBOX. --regextrans2 's¤INBOX.INBOX¤INBOX¤'
} }
useheader()
{
if test X`hostname` = X"plume"; then
echo3 Here is plume
./imapsync \
--host2 plume --user2 tata@est.belle \
--passfile2 /var/tmp/secret.tata \
--host1 loul --user1 tata \
--passfile1 /var/tmp/secret.tata \
--folder INBOX.yop.yap \
--useheader 'Message-ID' \
--dry --debug
echo 'rm /home/vmail/tata/.yop.yap/cur/*'
else
:
fi
}
regexmess() regexmess()
{ {
if test X`hostname` = X"plume"; then if test X`hostname` = X"plume"; then
@ -633,7 +655,8 @@ test $# -eq 0 && run_tests \
foldersizes \ foldersizes \
big_transfert_sizes_only \ big_transfert_sizes_only \
regexmess \ regexmess \
useheader \
# selective tests # selective tests