1
0
mirror of https://github.com/imapsync/imapsync.git synced 2024-11-17 08:12:48 +01:00
imapsync/W/patches/imapsync.1.282.patch
Nick Bebout c08a56e486 1.504
2012-09-02 19:08:57 -05:00

463 lines
15 KiB
Diff

--- imapsync.ORIG 2009-05-21 02:30:56.828125000 -0400
+++ imapsync 2009-05-21 02:35:55.984375000 -0400
@@ -72,13 +72,14 @@
[--useheader <string>] [--useheader <string>]
[--skipsize] [--allowsizemismatch]
[--delete] [--delete2]
- [--expunge] [--expunge1] [--expunge2]
+ [--expunge] [--expunge1] [--expunge2] [--uidexpunge2]
[--subscribed] [--subscribe]
[--nofoldersizes]
[--dry]
[--debug] [--debugimap]
[--timeout <int>] [--fast]
[--split1] [--split2]
+ [--reconnectretry1 <int>] [--reconnectretry2 <int>]
[--version] [--help]
=cut
@@ -358,6 +359,7 @@
--expunge
--expunge1
--expunge2
+--uidexpunge2
--maxage
--minage
--maxsize
@@ -456,7 +458,7 @@
$skipheader, @useheader,
$skipsize, $allowsizemismatch, $foldersizes, $buffersize,
$delete, $delete2,
- $expunge, $expunge1, $expunge2, $dry,
+ $expunge, $expunge1, $expunge2, $uidexpunge2, $dry,
$justfoldersizes,
$authmd5,
$subscribed, $subscribe,
@@ -474,6 +476,7 @@
$authuser1, $authuser2,
$authmech1, $authmech2,
$split1, $split2,
+ $reconnectretry1, $reconnectretry2,
$tests, $test_builder,
$allow3xx, $justlogin,
);
@@ -735,12 +738,12 @@
$debugimap and print "From connection\n";
$from = login_imap($host1, $port1, $user1, $password1,
$debugimap, $timeout, $fastio1, $ssl1,
- $authmech1, $authuser1);
+ $authmech1, $authuser1, $reconnectretry1);
$debugimap and print "To connection\n";
$to = login_imap($host2, $port2, $user2, $password2,
$debugimap, $timeout, $fastio2, $ssl2,
- $authmech2, $authuser2);
+ $authmech2, $authuser2, $reconnectretry2);
# history
@@ -751,13 +754,13 @@
sub login_imap {
my($host, $port, $user, $password,
$debugimap, $timeout, $fastio,
- $ssl, $authmech, $authuser) = @_;
+ $ssl, $authmech, $authuser, $reconnectretry) = @_;
my ($imap);
$imap = Mail::IMAPClient->new();
$imap->Ssl($ssl) if ($ssl);
- $imap->Clear(20);
+ $imap->Clear(5);
$imap->Server($host);
$imap->Port($port);
$imap->Fast_io($fastio);
@@ -766,7 +769,12 @@
$imap->Peek(1);
$imap->Debug($debugimap);
$timeout and $imap->Timeout($timeout);
-
+
+ ( Mail::IMAPClient->VERSION =~ /^2/ or !$imap->can("Reconnectretry"))
+ ? warn("--reconnectretry* requires IMAPClient >= 3.17\n")
+ : $imap->Reconnectretry($reconnectretry)
+ if ($reconnectretry);
+
#$imap->connect()
myconnect($imap)
or die "Can not open imap connection on [$host] with user [$user]: $@\n";
@@ -831,13 +839,13 @@
-#print "From capability: ", join(" ", $from->capability()), "\n";
-#print "To capability: ", join(" ", $to->capability()), "\n";
+$debug and print "From capability: ", join(" ", $from->capability()), "\n";
+$debug and print "To capability: ", join(" ", $to->capability()), "\n";
die unless $from->IsAuthenticated();
-print "host1 :state Authenticated\n";
+print "host1: state Authenticated\n";
die unless $to->IsAuthenticated();
-print "host2 :state Authenticated\n";
+print "host2: state Authenticated\n";
exit(0) if ($justlogin);
@@ -1100,13 +1108,17 @@
$debug and print "Calling namespace capability\n";
if ($imap->has_capability("namespace")) {
$sep_out = $imap->separator();
- return($sep_out);
+ return($sep_out) if defined $sep_out;
+ warn
+ "NAMESPACE request failed for ",
+ $imap->Server(), ": ", $imap->LastError, "\n";
+ exit(1);
}
else{
- print
+ warn
"No NAMESPACE capability in imap server ",
$imap->Server(),"\n",
- "Give the separator caracter with the $sep_opt option\n";
+ "Give the separator character with the $sep_opt option\n";
exit(1);
}
}
@@ -1133,9 +1145,9 @@
}
unless ($imap->select($folder)) {
warn
- "$side Folder $folder: Could not select ",
+ "$side Folder $folder: Could not select: ",
$imap->LastError, "\n";
- #$error++;
+ $error++;
next;
}
if (defined($maxage) or defined($minage)) {
@@ -1319,9 +1331,9 @@
unless ($from->select($f_fold)) {
warn
- "From Folder $f_fold: Could not select ",
+ "From Folder $f_fold: Could not select: ",
$from->LastError, "\n";
- #$error++;
+ $error++;
next FOLDER;
}
if ( ! exists($t_folders_list{$t_fold})) {
@@ -1329,7 +1341,7 @@
print "Creating folder [$t_fold]\n";
unless ($dry){
unless ($to->create($t_fold)){
- warn "Couldn't create [$t_fold]",
+ warn "Couldn't create [$t_fold]: ",
$to->LastError,"\n";
$error++;
next FOLDER;
@@ -1344,9 +1356,9 @@
unless ($to->select($t_fold)) {
warn
- "To Folder $t_fold: Could not select ",
+ "To Folder $t_fold: Could not select: ",
$to->LastError, "\n";
- #$error++;
+ $error++;
next FOLDER;
}
@@ -1384,17 +1396,22 @@
last FOLDER if $from->IsUnconnected();
last FOLDER if $to->IsUnconnected();
- my $f_heads = $from->parse_headers([@f_msgs],
- @useheader)if (@f_msgs) ;
+ my ($f_heads, $f_fir) = ({}, {});
+ $f_heads = $from->parse_headers([@f_msgs], @useheader) if (@f_msgs);
$debug and print "Time headers: ", timenext(), " s\n";
last FOLDER if $from->IsUnconnected();
- last FOLDER if $to->IsUnconnected();
- my $f_fir = $from->fetch_hash("FLAGS",
- "INTERNALDATE",
- "RFC822.SIZE") if (@f_msgs);
+
+ $f_fir = $from->fetch_hash("FLAGS", "INTERNALDATE", "RFC822.SIZE")
+ if (@f_msgs);
$debug and print "Time fir: ", timenext(), " s\n";
+ unless ($f_fir) {
+ warn
+ "From Folder $f_fold: Could not fetch_hash ",
+ scalar(@f_msgs), " msgs: ", $from->LastError, "\n";
+ $error++;
+ next FOLDER;
+ }
last FOLDER if $from->IsUnconnected();
- last FOLDER if $to->IsUnconnected();
foreach my $m (@f_msgs) {
unless (parse_header_msg1($from, $m, $f_heads, $f_fir, "F", \%f_hash)) {
@@ -1407,25 +1424,21 @@
$debug and print "Time headers: ", timenext(), " s\n";
print "++++ To [$t_fold] Parse 1 ++++\n";
- last FOLDER if $from->IsUnconnected();
- last FOLDER if $to->IsUnconnected();
- my $t_heads = $to->parse_headers([@t_msgs],
- @useheader) if (@t_msgs);
+ my ($t_heads, $t_fir) = ({}, {});
+ $t_heads = $to->parse_headers([@t_msgs], @useheader) if (@t_msgs);
$debug and print "Time headers: ", timenext(), " s\n";
- last FOLDER if $from->IsUnconnected();
last FOLDER if $to->IsUnconnected();
- my $t_fir = $to->fetch_hash("FLAGS",
- "INTERNALDATE",
- "RFC822.SIZE") if (@t_msgs);
+
+ $t_fir = $to->fetch_hash("FLAGS", "INTERNALDATE", "RFC822.SIZE")
+ if (@t_msgs);
$debug and print "Time fir: ", timenext(), " s\n";
- last FOLDER if $from->IsUnconnected();
last FOLDER if $to->IsUnconnected();
foreach my $m (@t_msgs) {
parse_header_msg1($to, $m, $t_heads, $t_fir, "T", \%t_hash);
}
$debug and print "Time headers: ", timenext(), " s\n";
-
+
print "++++ Verifying [$f_fold] -> [$t_fold] ++++\n";
# messages in "from" that are not good in "to"
@@ -1439,18 +1452,31 @@
if($delete2) {
+ my @expunge;
foreach my $m_id (@t_hash_keys_sorted_by_uid) {
#print "$m_id ";
unless (exists($f_hash{$m_id})) {
my $t_msg = $t_hash{$m_id}{'m'};
- print "deleting message $m_id $t_msg\n";
- unless ($dry) {
- last FOLDER if $from->IsUnconnected();
- last FOLDER if $to->IsUnconnected();
+ my $flags = $t_hash{$m_id}{'F'} || "";
+ my $isdel = $flags =~ /\B\\Deleted\b/ ? 1 : 0;
+ print "deleting message $m_id $t_msg\n"
+ if ! $isdel;
+ push(@expunge,$t_msg) if $uidexpunge2;
+ unless ($dry or $isdel) {
$to->delete_message($t_msg);
+ last FOLDER if $to->IsUnconnected();
}
}
}
+
+ my $cnt = scalar @expunge;
+ if(@expunge and !$to->can("uidexpunge")) {
+ warn "uidexpunge not supported (< IMAPClient 3.17)\n";
+ }
+ elsif(@expunge) {
+ print "uidexpunge $cnt message(s)\n";
+ $to->uidexpunge(\@expunge) if !$dry;
+ }
}
MESS: foreach my $m_id (@f_hash_keys_sorted_by_uid) {
@@ -1475,7 +1501,7 @@
$string = $from->message_string($f_msg);
unless (defined($string)) {
warn
- "Could not fetch message #$f_msg from $f_fold ",
+ "Could not fetch message #$f_msg from $f_fold: ",
$from->LastError, "\n";
$error++;
$mess_size_total_error += $f_size;
@@ -1591,10 +1617,10 @@
if($delete) {
print "Deleting msg #$f_msg in folder $f_fold\n";
unless($dry) {
- last FOLDER if $from->IsUnconnected();
- last FOLDER if $to->IsUnconnected();
$from->delete_message($f_msg);
+ last FOLDER if $from->IsUnconnected();
$from->expunge() if ($expunge);
+ last FOLDER if $from->IsUnconnected();
}
}
}
@@ -1612,44 +1638,31 @@
}
$fast and next MESS;
- #$debug and print "MESSAGE $m_id\n";
+ #$debug and print "MESSAGE $m_id\n";
my $t_size = $t_hash{$m_id}{'s'};
my $t_msg = $t_hash{$m_id}{'m'};
-
-
- $debug and print "Setting flags\n";
- last FOLDER if $from->IsUnconnected();
- last FOLDER if $to->IsUnconnected();
+ # used cached flag values for efficiency
+ my $flags_f = $f_hash{$m_id}{'F'} || "";
+ my $flags_t = $t_hash{$m_id}{'F'} || "";
- my (@flags_f,@flags_t);
- my $flags_f_rv = $from->flags($f_msg);
- @flags_f = @{$flags_f_rv} if ref($flags_f_rv);
-
# No flag \Recent here, no ?
- my $flags_f = join(" ", @flags_f);
-
$flags_f = flags_regex($flags_f) if @regexflag;
-
- # This add or change flags but no flag are removed with this
- $to->store($t_msg,
- "+FLAGS.SILENT (" . $flags_f . ")"
- ) unless ($dry);
-
- # I think one IsUnconnected() is enough before all flags operations.
- #last FOLDER if $to->IsUnconnected();
-
- my $flags_t_rv = $to->flags($t_msg);
- #last FOLDER if $to->IsUnconnected();
- @flags_t = @{$flags_t_rv} if ref($flags_t_rv);
- my $flags_t = join(" ", @flags_t);
- $debug and print
- "flags from: $flags_f\n",
- "flags to : $flags_t\n";
-
+ $debug and print "Setting flags from($flags_f) to($flags_t)\n";
+
+ # This add or change flags but no flag are removed with this
+ $to->store($t_msg, "+FLAGS.SILENT ($flags_f)" )
+ if (!$dry and $flags_f ne $flags_t);
+ last FOLDER if $to->IsUnconnected();
$debug and do {
+ my @flags_t = @{ $to->flags($t_msg) || [] };
+ last FOLDER if $to->IsUnconnected();
+
+ print "flags from: $flags_f\n",
+ "flags to : @flags_t\n";
+
print "Looking dates\n";
#my $d_f = $from->internaldate($f_msg);
#my $d_t = $to->internaldate($t_msg);
@@ -1657,7 +1670,7 @@
my $d_t = $t_hash{$m_id}{'D'};
print
"idate from: $d_f\n",
- "idate to : $d_t\n";
+ "idate to : $d_t\n";
#unless ($d_f eq $d_t) {
# print "!!! Dates differ !!!\n";
@@ -1673,8 +1686,7 @@
if ($opt_G){
print "Deleting msg f:#$t_msg in folder $t_fold\n";
$to->delete_message($t_msg) unless ($dry);
- # $opt_G is fake
- #last FOLDER if $to->IsUnconnected();
+ last FOLDER if $to->IsUnconnected();
}
}
else {
@@ -1684,10 +1696,10 @@
if($delete) {
print "Deleting msg #$f_msg in folder $f_fold\n";
unless($dry) {
- last FOLDER if $from->IsUnconnected();
- last FOLDER if $to->IsUnconnected();
$from->delete_message($f_msg);
+ last FOLDER if $from->IsUnconnected();
$from->expunge() if ($expunge);
+ last FOLDER if $from->IsUnconnected();
}
}
}
@@ -1713,21 +1725,31 @@
#
# can be tested with a "killall /usr/bin/imapd" (or equivalent) in command line.
#
+sub _filter {
+ my $str = shift or return "";
+ my $sz = 64;
+ my $len = length($str);
+ if ( ! $debug and $len > $sz*2 ) {
+ my $beg = substr($str, 0, $sz);
+ my $end = substr($str, -$sz, $sz);
+ $str = $beg . "..." . $end;
+ }
+ $str =~ s/\012?\015$//;
+ return "(len=$len) " . $str;
+}
+
sub lost_connection {
my($imap, $error_message) = @_;
if ( $imap->IsUnconnected() ) {
$error++;
+ my $lcomm = $imap->LastIMAPCommand || "";
my $einfo = $imap->LastError || @{$imap->History}[-1] || "";
- my $sz = 64;
- # if einfo is long try reduce to a more reasonable size
- if ( ! $debug and length($einfo) > $sz*2 ) {
- my $beg = substr($einfo, 0, $sz);
- my $end = substr($einfo, -$sz, $sz);
- $einfo = $beg . "..." . $end;
- }
- chomp($einfo);
- $einfo = ": $einfo" if $einfo;
- warn("error: lost connection $error_message $einfo\n");
+
+ # if string is long try reduce to a more reasonable size
+ $lcomm = _filter($lcomm);
+ $einfo = _filter($einfo);
+ warn("error: last command: $lcomm\n") if ($debug && $lcomm);
+ warn("error: lost connection $error_message", $einfo, "\n");
return(1);
}else{
return(0);
@@ -1847,6 +1869,7 @@
"expunge!" => \$expunge,
"expunge1!" => \$expunge1,
"expunge2!" => \$expunge2,
+ "uidexpunge2!" => \$uidexpunge2,
"subscribed!" => \$subscribed,
"subscribe!" => \$subscribe,
"justbanner!" => \$justbanner,
@@ -1871,6 +1894,8 @@
"authuser2=s" => \$authuser2,
"split1=i" => \$split1,
"split2=i" => \$split2,
+ "reconnectretry1=i" => \$reconnectretry1,
+ "reconnectretry2=i" => \$reconnectretry2,
"tests" => \$tests,
"allow3xx!" => \$allow3xx,
"justlogin!" => \$justlogin,
@@ -2088,6 +2113,8 @@
it will change in future releases.
--expunge1 : expunge messages on source account.
--expunge2 : expunge messages on target account.
+--uidexpunge2 : uidexpunge messages on the destination imap server
+ that are not on the source server, requires --delete2
--syncinternaldates : sets the internal dates on host2 same as host1.
Turned on by default.
--idatefromheader : sets the internal dates on host2 same as the
@@ -2132,6 +2159,8 @@
and exit.
--justfolders : just do things about folders (ignore messages).
--fast : be faster (just does not sync flags).
+--reconnectretry1 <int>: reconnect if connection is lost up to <int> times
+--reconnectretry2 <int>: reconnect if connection is lost up to <int> times
--split1 <int> : split the requests in several parts on source server.
<int> is the number of messages handled per request.
default is like --split1 1000