From f6f2c48fa4b14b9a9f1f23fef3ad83c46c6879dd Mon Sep 17 00:00:00 2001 From: Nick Bebout Date: Sat, 12 Mar 2011 02:44:13 +0000 Subject: [PATCH] 1.123 --- CREDITS | 10 + ChangeLog | 13 +- README | 8 +- TODO | 13 + VERSION | 2 +- imapsync | 27 +- patches/imapsync--justcopy.patch | 535 +++++++++++++++++++++++++++++++ 7 files changed, 595 insertions(+), 13 deletions(-) create mode 100644 patches/imapsync--justcopy.patch diff --git a/CREDITS b/CREDITS index 1a41be6..9dafa29 100644 --- a/CREDITS +++ b/CREDITS @@ -1,5 +1,15 @@ #!/bin/cat +Dan Wang +Gave "Novell NetMail and Novell Groupwise" +Reported bug Novell NetMail flags undef + + +Per olof Ljungmark +Gave +"Netscape Messaging Server 4.15 Patch 7 (built Sep 12 2001)) +Cyrus IMAP4 v2.2.10" + Harald A. Irmer Huge migration with mbox format pb. Several problems. diff --git a/ChangeLog b/ChangeLog index 33f766f..f00e556 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,15 +1,24 @@ RCS file: RCS/imapsync,v Working file: imapsync -head: 1.121 +head: 1.123 branch: locks: strict access list: symbolic names: keyword substitution: kv -total revisions: 121; selected revisions: 121 +total revisions: 123; selected revisions: 123 description: ---------------------------- +revision 1.123 +date: 2005/03/19 04:25:46; author: gilles; state: Exp; lines: +17 -6 +Added check about flags undef +Bug reported from Novell NetMail by Dan Wang +---------------------------- +revision 1.122 +date: 2005/03/19 04:11:33; author: gilles; state: Exp; lines: +8 -6 +Updated Success stories +---------------------------- revision 1.121 date: 2005/02/01 04:03:30; author: gilles; state: Exp; lines: +7 -5 Added links imapcopy and migrationtool diff --git a/README b/README index 6645671..4ab0648 100644 --- a/README +++ b/README @@ -2,7 +2,7 @@ NAME imapsync - IMAP synchronization, copy or migration tool. Synchronize mailboxes between two imap servers. Good at IMAP migration. - $Revision: 1.121 $ + $Revision: 1.123 $ INSTALL imapsync works fine under any Unix OS. @@ -165,7 +165,8 @@ IMAP SERVERS - CommunicatePro server (Redhat 8.0) - Courier IMAP 1.5.1, 2.2.0, 2.1.1, 2.2.1 - Critical Path (7.0.020) - - Cyrus IMAP 1.5, 1.6, 2.1, 2.1.15, 2.1.16, 2.2.1, Cyrus 2.2.2-BETA. + - Cyrus IMAP 1.5, 1.6, 2.1, 2.1.15, 2.1.16, + 2.2.1, 2.2.2-BETA, 2.2.10 - DBMail 1.2.1 - Dovecot 0.99.10.4 - Domino (Notes) 6.5, 5.0.6 @@ -174,6 +175,7 @@ IMAP SERVERS - MDaemon 7.0.1 - MS Exchange Server 5.5 - Netscape Mail Server 3.6 (Wintel !) + - Netscape Messaging Server 4.15 Patch 7 - OpenWave - Qualcomm Worldmail (NT) - SunONE Messaging server 5.2, 6.0 (SUN JES - Java Enterprise System) @@ -242,5 +244,5 @@ AUTHOR teaching free open and gratis softwares. Don't hesitate to pay him for that services. - $Id: imapsync,v 1.121 2005/02/01 04:03:30 gilles Exp $ + $Id: imapsync,v 1.123 2005/03/19 04:25:46 gilles Exp $ diff --git a/TODO b/TODO index e7a1dc2..4ff00f2 100644 --- a/TODO +++ b/TODO @@ -1,6 +1,19 @@ TODO file for imapsync ---------------------- +Read: +http://www.washington.edu/imap/documentation/commndmt.txt.html + +Talk about : +"I think notes is right but MS Eudora is bad with dates. +(netscape or thunderbird is ok with dates) +use the option --syncinternaldates " + + +Add usage about --regextrans2 +To remove INBOX. in the name of destination folders : +--regextrans2 's/^INBOX\.(.+)/$1/' + Add cyrus link about INBOX. namespace http://asg.web.cmu.edu/cyrus/download/imapd/altnamespace.html diff --git a/VERSION b/VERSION index 099b05d..0fbe170 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -1.121 +1.123 diff --git a/imapsync b/imapsync index a35ec35..29f2e59 100755 --- a/imapsync +++ b/imapsync @@ -6,7 +6,7 @@ imapsync - IMAP synchronization, copy or migration tool. Synchronize mailboxes between two imap servers. Good at IMAP migration. -$Revision: 1.121 $ +$Revision: 1.123 $ =head1 INSTALL @@ -190,7 +190,8 @@ Success stories reported (softwares in alphabetic order) : - CommunicatePro server (Redhat 8.0) - Courier IMAP 1.5.1, 2.2.0, 2.1.1, 2.2.1 - Critical Path (7.0.020) - - Cyrus IMAP 1.5, 1.6, 2.1, 2.1.15, 2.1.16, 2.2.1, Cyrus 2.2.2-BETA. + - Cyrus IMAP 1.5, 1.6, 2.1, 2.1.15, 2.1.16, + 2.2.1, 2.2.2-BETA, 2.2.10 - DBMail 1.2.1 - Dovecot 0.99.10.4 - Domino (Notes) 6.5, 5.0.6 @@ -199,6 +200,7 @@ Success stories reported (softwares in alphabetic order) : - MDaemon 7.0.1 - MS Exchange Server 5.5 - Netscape Mail Server 3.6 (Wintel !) + - Netscape Messaging Server 4.15 Patch 7 - OpenWave - Qualcomm Worldmail (NT) - SunONE Messaging server 5.2, 6.0 (SUN JES - Java Enterprise System) @@ -284,7 +286,7 @@ Gilles LAMIRAL earn his living writing, installing, configuring and teaching free open and gratis softwares. Don't hesitate to pay him for that services. -$Id: imapsync,v 1.121 2005/02/01 04:03:30 gilles Exp $ +$Id: imapsync,v 1.123 2005/03/19 04:25:46 gilles Exp $ =cut @@ -327,7 +329,7 @@ my( use vars qw ($opt_G); # missing code for this will be option. -$rcs = ' $Id: imapsync,v 1.121 2005/02/01 04:03:30 gilles Exp $ '; +$rcs = ' $Id: imapsync,v 1.123 2005/03/19 04:25:46 gilles Exp $ '; $rcs =~ m/,v (\d+\.\d+)/; $VERSION = ($1) ? $1 : "UNKNOWN"; @@ -364,8 +366,8 @@ $error=0; my $banner = join("", '$RCSfile: imapsync,v $ ', - '$Revision: 1.121 $ ', - '$Date: 2005/02/01 04:03:30 $ ', + '$Revision: 1.123 $ ', + '$Date: 2005/03/19 04:25:46 $ ', "\n", "Mail::IMAPClient version used here is ", $VERSION_IMAPClient, " auth md5 : $md5_supported", @@ -803,7 +805,18 @@ FOLDER: foreach my $f_fold (@f_folders) { $debug and print "internal date from 1: [$d]\n"; } - my $flags_f = join(" ", @{$from->flags($f_msg)}); + my $flags_f_rv = $from->flags($f_msg); + my @flags_f; + my $flags_f; + + if (ref($flags_f_rv)) { + @flags_f = @{$flags_f_rv}; + $flags_f = join(" ", @flags_f); + }else{ + $flags_f = ""; + } + + #$flags_f = join(" ", @{$from->flags($f_msg)}); # RFC 2060 : This flag can not be altered by the client $flags_f =~ s@\\Recent@@g; diff --git a/patches/imapsync--justcopy.patch b/patches/imapsync--justcopy.patch new file mode 100644 index 0000000..63f9c7f --- /dev/null +++ b/patches/imapsync--justcopy.patch @@ -0,0 +1,535 @@ +--- imapsync.orig 2005-02-11 14:27:53.508176000 -0600 ++++ imapsync 2005-02-14 11:39:31.241157000 -0600 +@@ -1,6 +1,6 @@ + #!/usr/bin/perl -w + +-=head1 NAME ++=head1 NAME + + imapsync - IMAP synchronization, copy or migration + tool. Synchronize mailboxes between two imap servers. Good +@@ -35,9 +35,9 @@ + imapsync + + imapsync [--host1 server1] [--port1 ] +- [--user1 ] [--passfile1 ] ++ [--user1 ] [--passfile1 ] + [--host2 server2] [--port2 ] +- [--user2 ] [--passfile2 ] ++ [--user2 ] [--passfile2 ] + [--folder --folder ...] + [--include ] [--exclude ] + [--prefix2 ] +@@ -55,14 +55,14 @@ + [--debug] [--debugimap] + [--timeout ] + [--version] [--help] +- ++ + =cut + # comment + =pod + + =head1 DESCRIPTION + +-The command imapsync is a tool allowing incremental and recursive ++The command imapsync is a tool allowing incremental and recursive + imap transfer from one mailbox to another. + + We sometimes need to transfer mailboxes from one imap server to +@@ -133,10 +133,10 @@ + imapsync will exit with a 0 status (return code) if everything went good. + Otherwise, it exits with a non-zero status. + +-So if you have a buggy internet connection, you can use this loop ++So if you have a buggy internet connection, you can use this loop + in a Bourne shell: + +- while ! imapsync ...; do ++ while ! imapsync ...; do + echo imapsync not complete + done + +@@ -184,7 +184,7 @@ + + =head1 IMAP SERVERS + +-Success stories reported (softwares in alphabetic order) : ++Success stories reported (softwares in alphabetic order) : + + - BincImap 1.2.3 + - CommunicatePro server (Redhat 8.0) +@@ -223,7 +223,7 @@ + =head1 HUGE MIGRATION + + +-Have a special attention on options ++Have a special attention on options + --subscribed + --subscribe + --delete +@@ -244,7 +244,7 @@ + + And the shell program is just : + +-{ while IFS=';' read u1 p1 u2 p2; do ++{ while IFS=';' read u1 p1 u2 p2; do + imapsync --user1 $u1 --password1 $p1 --user2 $u2 --password2 $p2 ... + done ; } < file.csv + +@@ -266,7 +266,7 @@ + mailsync : http://mailsync.sourceforge.net/ + imapxfer : http://www.washington.edu/imap/ + part of the imap-utils from UW. +- mailutil : replace imapxfer in ++ mailutil : replace imapxfer in + part of the imap-utils from UW. + http://www.gsp.com/cgi-bin/man.cgi?topic=mailutil + imaprepl : http://www.bl0rg.net/software/ +@@ -308,10 +308,10 @@ + $syncinternaldates, $syncacls, + $maxsize, $maxage, + $skipheader, $skipsize, $foldersizes, +- $delete, $expunge, $dry, ++ $delete, $expunge, $dry, + $authmd5, + $subscribed, $subscribe, +- $version, $VERSION, $help, ++ $version, $VERSION, $help, + $justconnect, $justfolders, + $fast, + $mess_size_total_trans, +@@ -321,6 +321,7 @@ + $timeout, # whr (ESS/PRW) + $timestart, $timeend, $timediff, + $timesize, $timebefore, ++ $verbose, $justcopy + + ); + +@@ -362,7 +363,7 @@ + + $error=0; + +-my $banner = join("", ++my $banner = join("", + '$RCSfile: imapsync,v $ ', + '$Revision: 1.121 $ ', + '$Date: 2005/02/01 04:03:30 $ ', +@@ -426,7 +427,7 @@ + $to = login_imap($host2, $port2, $user2, $password2, $debugimap, $timeout); + + sub login_imap { +- my($host, $port, $user, $password, ++ my($host, $port, $user, $password, + $debugimap, $timeout, $authmech) = @_; + my $imap = Mail::IMAPClient->new(); + $imap->Server($host); +@@ -461,12 +462,12 @@ + print "$authmech not wanted by you\n"; + return; + } +- if ($imap->has_capability($authmech) ++ if ($imap->has_capability($authmech) + or $imap->has_capability("AUTH=$authmech")) { +- print "Server [", $imap->Server, ++ print "Server [", $imap->Server, + "] has capability $authmech\n"; + }else{ +- print "Server [", $imap->Server, ++ print "Server [", $imap->Server, + "] has NOT capability $authmech\n"; + return; + } +@@ -520,7 +521,7 @@ + + @t_folders = sort @{$to->folders()}; + +-my($f_sep,$t_sep); ++my($f_sep,$t_sep); + # what are the private folders separators for each server ? + + +@@ -543,8 +544,8 @@ + $sep_out = $imap->separator(); + return($sep_out); + }else{ +- print +- "No NAMESPACE capability in imap server ", ++ print ++ "No NAMESPACE capability in imap server ", + $imap->Server(),"\n", + "Give the separator caracter with the $sep_opt option\n"; + exit(1); +@@ -555,7 +556,7 @@ + print "From separator : [$f_sep]\n"; + print "To separator : [$t_sep]\n"; + +-if ($foldersizes) { ++if (!$justcopy and $foldersizes) { + my $tot = 0; + my $tmess = 0; + print "++++ Calculating sizes ++++\n"; +@@ -564,7 +565,7 @@ + my $smess = 0; + printf("From Folder %-25s", "[$f_fold]"); + unless ($from->select($f_fold)) { +- warn ++ warn + "From Folder $f_fold : Could not select ", + $from->LastError, "\n"; + $error++; +@@ -616,11 +617,11 @@ + + + +-print ++print + "From folders : ", map("[$_] ",@f_folders),"\n", + "To folders : ", map("[$_] ",@t_folders),"\n"; + +-print ++print + "From subscribed folders : ", map("[$_] ", sort keys(%fs_folders)), "\n"; + + sub separator_invert { +@@ -654,14 +655,14 @@ + print "To Folder [$t_fold]\n"; + + unless ($from->select($f_fold)) { +- warn ++ warn + "From Folder $f_fold : Could not select ", + $from->LastError, "\n"; + $error++; + next FOLDER; + } + +- unless ($to->exists($t_fold) or $to->select($t_fold)) { ++ unless ($to->exists($t_fold) or $to->select($t_fold)) { + print "To Folder $t_fold does not exist\n"; + print "Creating folder [$t_fold]\n"; + unless ($dry){ +@@ -675,9 +676,9 @@ + next FOLDER; + } + } +- +- unless ($to->select($t_fold)) { +- warn ++ ++ unless ($to->select($t_fold)) { ++ warn + "To Folder $t_fold : Could not select ", + $to->LastError, "\n"; + $error++; +@@ -708,6 +709,7 @@ + } + } + } ++ print "Time folders: ", timenext(), " s\n"; + + next FOLDER if ($justfolders); + +@@ -725,6 +727,7 @@ + $from->Clear(1); + $to->Clear(1); + ++ print "Time query: ", timenext(), " s\n"; + + print "From Buffer I/O : ", $from->Buffer(), "\n"; + print "To Buffer I/O : ", $to->Buffer(), "\n"; +@@ -733,49 +736,55 @@ + # print "From Buffer I/O : ", $from->Buffer(), "\n"; + # print "To Buffer I/O : ", $to->Buffer(), "\n"; + +- print "++++ From Parse 1 ++++\n"; +- +- my $f_heads = $from->parse_headers([@f_msgs],"ALL") if (@f_msgs) ; +- print "Time headers: ", timenext(), " s\n"; +- my $f_size = $from->fetch_hash("RFC822.SIZE") if (@f_msgs); +- print "Time sizes : ", timenext(), " s\n"; +- #my $f_flags = $from->flags(@f_msgs) ; +- #print "Time flags : ", timenext(), " s\n"; +- use Data::Dumper; +- #print Data::Dumper->Dump([$f_heads]); +- #print Data::Dumper->Dump([$f_flags]); +- +- #exit; +- foreach my $m (@f_msgs) { +- parse_header_msg1($m, $f_heads, $f_size, "F", \%f_hash); +- } +- print "Time headers: ", timenext(), " s\n"; +- +- print "\n++++ To Parse 1 ++++\n"; +- my $t_heads = $to->parse_headers([@t_msgs],"ALL") if (@t_msgs); +- print "Time headers: ", timenext(), " s\n"; +- my $t_size = $to->fetch_hash("RFC822.SIZE") if (@t_msgs); +- print "Time sizes : ", timenext(), " s\n"; +- #my $t_flags = $to->flags(@t_msgs) ; +- #print "Time flags : ", timenext(), " s\n"; +- +- foreach my $m (@t_msgs) { +- parse_header_msg1($m, $t_heads, $t_size, "T", \%t_hash); +- } +- print "Time headers: ", timenext(), " s\n"; +- #exit; +- +- print "\n++++ Verifying ++++\n"; +- # messages in "from" that are not good in "to" +- +- my @f_hash_keys_sorted_by_uid +- = sort {$f_hash{$a}{'m'} <=> $f_hash{$b}{'m'}} keys(%f_hash); +- +- #print map { $f_hash{$_}{'m'} . " "} @f_hash_keys_sorted_by_uid; +- +- MESS: foreach my $m_id (@f_hash_keys_sorted_by_uid) { +- my $f_size = $f_hash{$m_id}{'s'}; +- my $f_msg = $f_hash{$m_id}{'m'}; ++ # Define f_hash_keys_sorted_by_uid outside of if statement to keep ++ # Perl happy ++ my @f_hash_keys_sorted_by_uid = (); ++ if ($justcopy) { ++ print "++++ Copying ++++\n"; ++ } else { ++ print "++++ From Parse 1 ++++\n"; ++ ++ my $f_heads = $from->parse_headers([@f_msgs],"ALL") if (@f_msgs) ; ++ print "Time headers: ", timenext(), " s\n"; ++ my $f_size = $from->fetch_hash("RFC822.SIZE") if (@f_msgs); ++ print "Time sizes : ", timenext(), " s\n"; ++ #my $f_flags = $from->flags(@f_msgs) ; ++ #print "Time flags : ", timenext(), " s\n"; ++ use Data::Dumper; ++ #print Data::Dumper->Dump([$f_heads]); ++ #print Data::Dumper->Dump([$f_flags]); ++ ++ #exit; ++ foreach my $m (@f_msgs) { ++ parse_header_msg1($m, $f_heads, $f_size, "F", \%f_hash); ++ } ++ print "Time headers: ", timenext(), " s\n"; ++ ++ print "\n++++ To Parse 1 ++++\n"; ++ my $t_heads = $to->parse_headers([@t_msgs],"ALL") if (@t_msgs); ++ print "Time headers: ", timenext(), " s\n"; ++ my $t_size = $to->fetch_hash("RFC822.SIZE") if (@t_msgs); ++ print "Time sizes : ", timenext(), " s\n"; ++ #my $t_flags = $to->flags(@t_msgs) ; ++ #print "Time flags : ", timenext(), " s\n"; ++ ++ foreach my $m (@t_msgs) { ++ parse_header_msg1($m, $t_heads, $t_size, "T", \%t_hash); ++ } ++ print "Time headers: ", timenext(), " s\n"; ++ #exit; ++ ++ print "\n++++ Verifying ++++\n"; ++ # messages in "from" that are not good in "to" ++ @f_hash_keys_sorted_by_uid ++ = sort {$f_hash{$a}{'m'} <=> $f_hash{$b}{'m'}} keys(%f_hash); ++ ++ #print map { $f_hash{$_}{'m'} . " "} @f_hash_keys_sorted_by_uid; ++ } ++ ++ MESS: foreach my $m_id ($justcopy ? @f_msgs : @f_hash_keys_sorted_by_uid) { ++ my $f_size = $justcopy ? 0 : $f_hash{$m_id}{'s'}; ++ my $f_msg = $justcopy ? $m_id : $f_hash{$m_id}{'m'}; + # print "."; + if (defined $maxsize and $f_size > $maxsize) { + print "+ Skipping msg #$f_msg:$f_size in folder $f_fold (exceeds maxsize limit $maxsize bytes)\n"; +@@ -783,10 +792,10 @@ + next MESS; + } + $debug and print "+ key $m_id #$f_msg\n"; +- unless (exists($t_hash{$m_id})) { +- print "+ NO msg #$f_msg [$m_id] in $t_fold\n"; ++ unless (!$justcopy and exists($t_hash{$m_id})) { ++ $verbose and print "+ NO msg #$f_msg [$m_id] in $t_fold\n"; + # copy +- print "+ Copying msg #$f_msg:$f_size to folder $t_fold\n"; ++ $verbose and print "+ Copying msg #$f_msg:$f_size to folder $t_fold\n"; + my $string = $from->message_string($f_msg); + while (my $regexmess = shift(@regexmess)) { + $debug and print "eval \$string =~ $regexmess\n"; +@@ -809,7 +818,7 @@ + $flags_f =~ s@\\Recent@@g; + + my $new_id; +- print "flags from : [$flags_f][$d]\n"; ++ $verbose and print "flags from : [$flags_f][$d]\n"; + unless ($dry) { + unless($new_id = $to->append_string($t_fold,$string, $flags_f, $d)){ + warn "Couldn't append msg #$f_msg (Subject:[".$from->subject($f_msg)."]) to folder $t_fold: ", +@@ -820,9 +829,9 @@ + + }else{ + # good +- # $new_id is an id if the IMAP server has the ++ # $new_id is an id if the IMAP server has the + # UIDPLUS capability else just a ref +- print "Copied msg id [$f_msg] to folder $t_fold msg id [$new_id]\n"; ++ $verbose and print "Copied msg id [$f_msg] to folder $t_fold msg id [$new_id]\n"; + $mess_size_total_trans += $f_size; + $mess_trans += 1; + } +@@ -834,12 +843,12 @@ + $mess_skipped += 1; + } + +- $fast and next MESS; +- #$debug and print "MESSAGE $m_id\n"; ++ ($fast or $justcopy) and next MESS; ++ #$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"; ++ $debug and print "Setting flags\n"; + my (@flags_f,@flags_t); + my $flags_f_rv = $from->flags($f_msg); + @flags_f = @{$flags_f_rv} if ref($flags_f_rv); +@@ -852,16 +861,16 @@ + + my $flags_t_rv = $to->flags($t_msg); + @flags_t = @{$flags_t_rv} if ref($flags_t_rv); +- $debug and print ++ $debug and print + "flags from : @flags_f\n", + "flags to : @flags_t\n"; + + + $debug and do { +- print "Looking dates\n"; ++ print "Looking dates\n"; + my $d_f = $from->internaldate($f_msg); + my $d_t = $to->internaldate($t_msg); +- print ++ print + "idate from : $d_f\n", + "idate to : $d_t\n"; + #unless ($d_f eq $d_t) { +@@ -870,7 +879,7 @@ + }; + unless ($f_size == $t_size) { + # Bad size +- print ++ print + "Message $m_id SZ_BAD f:$f_msg:$f_size t:$t_msg:$t_size\n"; + # delete in to and recopy ? + # NO recopy CODE HERE. to be written if needed. +@@ -880,17 +889,17 @@ + $to->delete_message($t_msg) unless ($dry); + } + }else { +- # Good ++ # Good + $debug and print + "Message $m_id SZ_GOOD f:$f_msg:$f_size t:$t_msg:$t_size\n"; + if($delete) { +- print "Deleting msg #$f_msg in folder $f_fold\n"; ++ $verbose and print "Deleting msg #$f_msg in folder $f_fold\n"; + $from->delete_message($f_msg) unless ($dry); + $from->expunge() if ($expunge and not $dry); + } + } + } +-print "Time : ", timenext(), " s\n"; ++ print "Time : ", timenext(), " s\n"; + } + + $timeend = time(); +@@ -959,6 +968,8 @@ + "timeout=i" => \$timeout, + "skipheader=s" => \$skipheader, + "skipsize!" => \$skipsize, ++ "verbose!" => \$verbose, ++ "justcopy!" => \$justcopy, + ); + + $debug and print "get options: [$opt_ret]\n"; +@@ -1020,7 +1031,7 @@ + my $headstr; + $debug and print "Head NUM:", scalar(keys(%$head)), "\n"; + # no header -> return +- return unless(scalar(keys(%$head))); ++ return unless(scalar(keys(%$head))); + foreach my $h (sort keys(%$head)){ + foreach my $val (sort @{$head->{$h}}) { + # no 8-bit data in headers ! +@@ -1050,12 +1061,12 @@ + + my($file) = @_; + my $line = ""; +- ++ + open FILE, $file or die("$! $file"); + chomp($line = ); + close FILE; + $line = ($line) ? $line : "!EMPTY! $file"; +- return $line; ++ return $line; + } + + sub usage { +@@ -1063,7 +1074,7 @@ + + usage: $0 [options] + +-Several options are mandatory. ++Several options are mandatory. + + --host1 : "from" imap server. Mandatory. + --port1 : port to connect. Default is 143. +@@ -1085,7 +1096,7 @@ + --exclude : skip folders matching this regular expression + (only effective if neither --folder nor --subscribed + is specified) +---prefix2 : add prefix to all destination folders ++--prefix2 : add prefix to all destination folders + (usually INBOX. for cyrus imap servers) + --regextrans2 : Apply the whole regex to each destination folders. + --regexmess : Apply the whole regex to each message before transfer. +@@ -1101,7 +1112,7 @@ + are not really deleted. See expunge. + --expunge : expunge messages on source account. + expunge really deletes messages marked deleted. +- expunge is made at the begining on the ++ expunge is made at the begining on the + source server only. newly transfered messages + are expunged if option --expunge is given. + no expunge is done on destination account but +@@ -1110,12 +1121,12 @@ + --maxsize : skip messages larger than bytes + --maxage : skip messages older than days. + final stats (skipped) don't count older messages +---skipheader : Don't take into account header keyword ++--skipheader : Don't take into account header keyword + matching ex: --skipheader 'X.*' + --skipsize : Don't take message size into account. + --dry : do nothing, just print what would be done. + --subscribed : transfer only subscribed folders. +---subscribe : subscribe to the folders transfered on the ++--subscribe : subscribe to the folders transfered on the + "destination" server that are subscribed + on the "source" server. + --(no)foldersizes : Calculate the size of each "From" folder in bytes +@@ -1125,12 +1136,17 @@ + --debug : debug mode. + --debugimap : imap debug mode. + --version : print sotfware version. +---justconnect : just connect to both servers and print useful ++--justconnect : just connect to both servers and print useful + information. + --justfolders : just do things about folders (ignore messages). + --fast : be faster. + --timeout : imap connect timeout. + --help : print this. ++--verbose : print info for each message transferred. ++--justcopy : only copy messages. Implies nofoldersizes, fast and ++ nomaxsize. No synchronization, might create duplicate ++ messages. Ment to be used for fast migration of ++ messages to new (empty) IMAP accounts. + + Example: to synchronise imap account "foo" on "imap.truc.org" + to imap account "bar" on "imap.trac.org" \ No newline at end of file