mirror of
https://github.com/imapsync/imapsync.git
synced 2024-11-17 00:02:29 +01:00
1.169
This commit is contained in:
parent
25948aab90
commit
a7bd48cb25
21
CREDITS
21
CREDITS
@ -1,5 +1,26 @@
|
|||||||
#!/bin/cat
|
#!/bin/cat
|
||||||
|
|
||||||
|
I thank very much all of these people.
|
||||||
|
|
||||||
|
Kjetil Torgrim Homme
|
||||||
|
Gave a jumbo patch adding
|
||||||
|
--authuser
|
||||||
|
--authmech
|
||||||
|
--ssl
|
||||||
|
and many improvments.
|
||||||
|
|
||||||
|
|
||||||
|
Adam Kosmin
|
||||||
|
Succeed to migrate from cyrus with an admin
|
||||||
|
account and gave us the example. (see FAQ).
|
||||||
|
--authuser1 option
|
||||||
|
|
||||||
|
Kurt Hoffmann
|
||||||
|
Had a pb with a big message on Zimbra-IMAP.
|
||||||
|
Did he finally succed ? Yes
|
||||||
|
"a stupid setting in Zimbra that restricts the size of
|
||||||
|
emails that can be uploaded via IMAP"
|
||||||
|
|
||||||
Robert Terzi
|
Robert Terzi
|
||||||
Seems to have the mbox vs Maildir/ problem
|
Seems to have the mbox vs Maildir/ problem
|
||||||
and gave the --regexmess 's/\AFrom \w .*\n//'
|
and gave the --regexmess 's/\AFrom \w .*\n//'
|
||||||
|
@ -1,15 +1,19 @@
|
|||||||
|
|
||||||
RCS file: RCS/imapsync,v
|
RCS file: RCS/imapsync,v
|
||||||
Working file: imapsync
|
Working file: imapsync
|
||||||
head: 1.168
|
head: 1.169
|
||||||
branch:
|
branch:
|
||||||
locks: strict
|
locks: strict
|
||||||
access list:
|
access list:
|
||||||
symbolic names:
|
symbolic names:
|
||||||
keyword substitution: kv
|
keyword substitution: kv
|
||||||
total revisions: 168; selected revisions: 168
|
total revisions: 169; selected revisions: 169
|
||||||
description:
|
description:
|
||||||
----------------------------
|
----------------------------
|
||||||
|
revision 1.169
|
||||||
|
date: 2006/04/13 21:36:15; author: gilles; state: Exp; lines: +7 -6
|
||||||
|
Added Zimbra IMAP success.
|
||||||
|
----------------------------
|
||||||
revision 1.168
|
revision 1.168
|
||||||
date: 2006/04/02 01:49:10; author: gilles; state: Exp; lines: +32 -10
|
date: 2006/04/02 01:49:10; author: gilles; state: Exp; lines: +32 -10
|
||||||
Added --delete2 option: remove messages on destination that
|
Added --delete2 option: remove messages on destination that
|
||||||
|
21
FAQ
21
FAQ
@ -64,7 +64,26 @@ Q. I want the --folder 'MyFolder' option be recurse.
|
|||||||
|
|
||||||
R. Do not use the --folder option.
|
R. Do not use the --folder option.
|
||||||
Instead, use --include '^MyFolder'
|
Instead, use --include '^MyFolder'
|
||||||
Then the folder "MyFolder" and all its subfolders will be handled.
|
Then the folder "MyFolder" and all its subfolders will be handled
|
||||||
|
and only them.
|
||||||
|
|
||||||
|
======================================================================
|
||||||
|
Q. How to migrate from cyrus with an admin account ?
|
||||||
|
|
||||||
|
R. Use
|
||||||
|
--ssl1 --authuser1 AdminAccount ----password1 AdminAccountPassword
|
||||||
|
Here is an example:
|
||||||
|
imapsync \
|
||||||
|
--host1 server1 \
|
||||||
|
--ssl1 \
|
||||||
|
--host2 server2 \
|
||||||
|
--authuser1 AdminAccount \
|
||||||
|
--password1 AdminAccountPassword \
|
||||||
|
--user1 joe \
|
||||||
|
--user2 joe \
|
||||||
|
--password2 joespassonserver2 \
|
||||||
|
--exclude '^user\.'
|
||||||
|
|
||||||
|
|
||||||
======================================================================
|
======================================================================
|
||||||
Q. I have moved from Braunschweig to Graz, so I would like to have my whole
|
Q. I have moved from Braunschweig to Graz, so I would like to have my whole
|
||||||
|
7
README
7
README
@ -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.168 $
|
$Revision: 1.169 $
|
||||||
|
|
||||||
INSTALL
|
INSTALL
|
||||||
imapsync works fine under any Unix OS.
|
imapsync works fine under any Unix OS.
|
||||||
@ -192,7 +192,7 @@ IMAP SERVERS
|
|||||||
- DBMail 2.0.7 (GPL). But DBMail 1.2.1 works.
|
- DBMail 2.0.7 (GPL). But DBMail 1.2.1 works.
|
||||||
Patient and confident testers are welcome.
|
Patient and confident testers are welcome.
|
||||||
- dkimap4 2.39
|
- dkimap4 2.39
|
||||||
|
|
||||||
Success stories reported with the following imap servers (softwares
|
Success stories reported with the following imap servers (softwares
|
||||||
names are in alphabetic order) :
|
names are in alphabetic order) :
|
||||||
|
|
||||||
@ -222,6 +222,7 @@ IMAP SERVERS
|
|||||||
(RedHat uses UW like 2003.338rh) (OSI Approved)
|
(RedHat uses UW like 2003.338rh) (OSI Approved)
|
||||||
(http://www.washington.edu/imap/)
|
(http://www.washington.edu/imap/)
|
||||||
- UW - QMail v2.1
|
- UW - QMail v2.1
|
||||||
|
- Zimbra-IMAP 3.0.1 GA 160, 3.1.0 Build 279.
|
||||||
|
|
||||||
Please report to the author any success or bad story with imapsync and
|
Please report to the author any success or bad story with imapsync and
|
||||||
don't forget to mention the IMAP server software names and version on
|
don't forget to mention the IMAP server software names and version on
|
||||||
@ -289,5 +290,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.168 2006/04/02 01:49:10 gilles Exp $
|
$Id: imapsync,v 1.169 2006/04/13 21:36:15 gilles Exp $
|
||||||
|
|
||||||
|
2
TODO
2
TODO
@ -1,6 +1,8 @@
|
|||||||
TODO file for imapsync
|
TODO file for imapsync
|
||||||
----------------------
|
----------------------
|
||||||
|
|
||||||
|
Add --verbose from Kjetil jumbo patch.
|
||||||
|
|
||||||
Talk about mbox and maildir format when "Invalid header"
|
Talk about mbox and maildir format when "Invalid header"
|
||||||
problem is encountered.
|
problem is encountered.
|
||||||
|
|
||||||
|
@ -1,10 +1,8 @@
|
|||||||
Project: imapsync
|
Project: imapsync
|
||||||
Version: 1.167
|
Version: 1.168
|
||||||
Release-Focus: Minor feature enhancements
|
Release-Focus: Major bugfixes
|
||||||
Hide: Y
|
Hide: Y
|
||||||
Home-Page-URL: http://www.linux-france.org/prj/imapsync/
|
Home-Page-URL: http://www.linux-france.org/prj/imapsync/
|
||||||
Gzipped-Tar-URL: http://www.linux-france.org/prj/imapsync/dist/
|
Gzipped-Tar-URL: http://www.linux-france.org/prj/imapsync/dist/
|
||||||
|
|
||||||
Added --delete2 option: removes messages on destination that
|
Code cleanup.
|
||||||
are not on the source server.
|
|
||||||
|
|
||||||
|
13
imapsync
13
imapsync
@ -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.168 $
|
$Revision: 1.169 $
|
||||||
|
|
||||||
=head1 INSTALL
|
=head1 INSTALL
|
||||||
|
|
||||||
@ -221,7 +221,7 @@ Failure stories reported with the following imap servers :
|
|||||||
- DBMail 2.0.7 (GPL). But DBMail 1.2.1 works.
|
- DBMail 2.0.7 (GPL). But DBMail 1.2.1 works.
|
||||||
Patient and confident testers are welcome.
|
Patient and confident testers are welcome.
|
||||||
- dkimap4 2.39
|
- dkimap4 2.39
|
||||||
|
|
||||||
Success stories reported with the following imap servers
|
Success stories reported with the following imap servers
|
||||||
(softwares names are in alphabetic order) :
|
(softwares names are in alphabetic order) :
|
||||||
|
|
||||||
@ -251,6 +251,7 @@ Success stories reported with the following imap servers
|
|||||||
(RedHat uses UW like 2003.338rh) (OSI Approved)
|
(RedHat uses UW like 2003.338rh) (OSI Approved)
|
||||||
(http://www.washington.edu/imap/)
|
(http://www.washington.edu/imap/)
|
||||||
- UW - QMail v2.1
|
- UW - QMail v2.1
|
||||||
|
- Zimbra-IMAP 3.0.1 GA 160, 3.1.0 Build 279.
|
||||||
|
|
||||||
Please report to the author any success or bad story with
|
Please report to the author any success or bad story with
|
||||||
imapsync and don't forget to mention the IMAP server
|
imapsync and don't forget to mention the IMAP server
|
||||||
@ -339,7 +340,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.168 2006/04/02 01:49:10 gilles Exp $
|
$Id: imapsync,v 1.169 2006/04/13 21:36:15 gilles Exp $
|
||||||
|
|
||||||
=cut
|
=cut
|
||||||
|
|
||||||
@ -395,7 +396,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.168 2006/04/02 01:49:10 gilles Exp $ ';
|
$rcs = ' $Id: imapsync,v 1.169 2006/04/13 21:36:15 gilles Exp $ ';
|
||||||
$rcs =~ m/,v (\d+\.\d+)/;
|
$rcs =~ m/,v (\d+\.\d+)/;
|
||||||
$VERSION = ($1) ? $1 : "UNKNOWN";
|
$VERSION = ($1) ? $1 : "UNKNOWN";
|
||||||
|
|
||||||
@ -432,8 +433,8 @@ $error=0;
|
|||||||
|
|
||||||
my $banner = join("",
|
my $banner = join("",
|
||||||
'$RCSfile: imapsync,v $ ',
|
'$RCSfile: imapsync,v $ ',
|
||||||
'$Revision: 1.168 $ ',
|
'$Revision: 1.169 $ ',
|
||||||
'$Date: 2006/04/02 01:49:10 $ ',
|
'$Date: 2006/04/13 21:36:15 $ ',
|
||||||
"\n",
|
"\n",
|
||||||
"Mail::IMAPClient version used here is ",
|
"Mail::IMAPClient version used here is ",
|
||||||
$VERSION_IMAPClient,"\n"
|
$VERSION_IMAPClient,"\n"
|
||||||
|
593
patches/imapsync-1.156-ssl-authusing.patch
Normal file
593
patches/imapsync-1.156-ssl-authusing.patch
Normal file
@ -0,0 +1,593 @@
|
|||||||
|
--- imapsync.orig 2006-03-13 16:34:48.430310000 +0100
|
||||||
|
+++ imapsync 2006-03-16 07:25:53.113435000 +0100
|
||||||
|
@@ -38,7 +38,7 @@
|
||||||
|
[--user1 <string>] [--passfile1 <string>]
|
||||||
|
[--host2 server2] [--port2 <num>]
|
||||||
|
[--user2 <string>] [--passfile2 <string>]
|
||||||
|
- [--noauthmd5]
|
||||||
|
+ [--authusing <string>] [--authmech <string>]
|
||||||
|
[--folder <string> --folder <string> ...]
|
||||||
|
[--include <regex>] [--exclude <regex>]
|
||||||
|
[--prefix2 <string>] [--prefix1 <string>]
|
||||||
|
@@ -46,7 +46,6 @@
|
||||||
|
[--sep1 <char>]
|
||||||
|
[--sep2 <char>]
|
||||||
|
[--justfolders] [--justfoldersizes] [--justconnect]
|
||||||
|
- [--syncinternaldates]
|
||||||
|
[--buffersize <int>]
|
||||||
|
[--syncacls]
|
||||||
|
[--regexmess <regex>] [--regexmess <regex>]
|
||||||
|
@@ -60,9 +59,10 @@
|
||||||
|
[--subscribed] [--subscribe]
|
||||||
|
[--nofoldersizes]
|
||||||
|
[--dry]
|
||||||
|
- [--debug] [--debugimap]
|
||||||
|
+ [--debug] [--debugimap] [--verbose]
|
||||||
|
[--timeout <int>] [--fast]
|
||||||
|
[--version] [--help]
|
||||||
|
+ [--ssl]
|
||||||
|
|
||||||
|
=cut
|
||||||
|
# comment
|
||||||
|
@@ -134,8 +134,14 @@
|
||||||
|
the password in a well protected file (600 or rw-------) is
|
||||||
|
the best solution.
|
||||||
|
|
||||||
|
-imasync is not protected against sniffers on the network so
|
||||||
|
-the passwords are in plain text.
|
||||||
|
+You may authenticate as one user (typically an admin user), but be
|
||||||
|
+authorized as someone else, which means you don't need to know every
|
||||||
|
+user's personal password. Specify --authusing ADMIN to enable this.
|
||||||
|
+In this case, --authmech PLAIN will be used, but otherwise,
|
||||||
|
+--authmech CRAM-MD5 is the default.
|
||||||
|
+
|
||||||
|
+To protect yourself from network sniffers, use --ssl to enable
|
||||||
|
+encryption.
|
||||||
|
|
||||||
|
=head1 EXIT STATUS
|
||||||
|
|
||||||
|
@@ -334,26 +340,27 @@
|
||||||
|
use Digest::MD5 qw(md5_base64);
|
||||||
|
use Term::ReadKey;
|
||||||
|
#use Digest::HMAC_MD5;
|
||||||
|
+use IO::Socket::SSL;
|
||||||
|
+use MIME::Base64;
|
||||||
|
|
||||||
|
eval { require 'usr/include/sysexits.ph' };
|
||||||
|
|
||||||
|
|
||||||
|
my(
|
||||||
|
- $rcs, $debug, $debugimap, $error,
|
||||||
|
+ $rcs, $debug, $debugimap, $verbose, $error,
|
||||||
|
$host1, $host2, $port1, $port2,
|
||||||
|
$user1, $user2, $password1, $password2, $passfile1, $passfile2,
|
||||||
|
@folder, $include, $exclude,
|
||||||
|
+ $authusing, $authmech,
|
||||||
|
$prefix1, $prefix2,
|
||||||
|
@regextrans2, @regexmess,
|
||||||
|
$sep1, $sep2,
|
||||||
|
- $syncinternaldates, $syncacls,
|
||||||
|
- $fastio1, $fastio2,
|
||||||
|
+ $syncacls,
|
||||||
|
$maxsize, $maxage, $minage,
|
||||||
|
$skipheader, @useheader,
|
||||||
|
$skipsize, $foldersizes, $buffersize,
|
||||||
|
$delete, $expunge, $expunge1, $expunge2, $dry,
|
||||||
|
$justfoldersizes,
|
||||||
|
- $authmd5,
|
||||||
|
$subscribed, $subscribe,
|
||||||
|
$version, $VERSION, $help,
|
||||||
|
$justconnect, $justfolders,
|
||||||
|
@@ -365,6 +372,7 @@
|
||||||
|
$timeout, # whr (ESS/PRW)
|
||||||
|
$timestart, $timeend, $timediff,
|
||||||
|
$timesize, $timebefore,
|
||||||
|
+ $usessl
|
||||||
|
);
|
||||||
|
|
||||||
|
use vars qw ($opt_G); # missing code for this will be option.
|
||||||
|
@@ -387,17 +395,10 @@
|
||||||
|
|
||||||
|
|
||||||
|
sub check_lib_version {
|
||||||
|
- # I know this is ugly, I should write a sort function
|
||||||
|
if ($VERSION_IMAPClient =~ m/(\d+)\.(\d+)\.(\d+)/) {
|
||||||
|
$debug and print "VERSION_IMAPClient $1 $2 $3\n";
|
||||||
|
- my($major,$minor,$sub) = ($1, $2, $3);
|
||||||
|
-
|
||||||
|
- return(1) if($major >=3);
|
||||||
|
- return(0) if($major <=1);
|
||||||
|
- return(1) if($minor >=3);
|
||||||
|
- return(0) if($minor <=1);
|
||||||
|
- return(1) if($sub >=8);
|
||||||
|
- return(0) if($sub <=7);
|
||||||
|
+ my $ver = sprintf("%c%c%c", $1, $2, $3);
|
||||||
|
+ return $ver ge v2.2.9;
|
||||||
|
}else{
|
||||||
|
return 0; # don't match regex => bad
|
||||||
|
}
|
||||||
|
@@ -420,7 +421,7 @@
|
||||||
|
}
|
||||||
|
|
||||||
|
get_options();
|
||||||
|
-print $banner;
|
||||||
|
+print $banner if $verbose;
|
||||||
|
|
||||||
|
sub missing_option {
|
||||||
|
my ($option) = @_;
|
||||||
|
@@ -428,88 +429,72 @@
|
||||||
|
}
|
||||||
|
|
||||||
|
$host1 || missing_option("--host1") ;
|
||||||
|
-$port1 = (defined($port1)) ? $port1 : 143;
|
||||||
|
+$port1 ||= defined $usessl ? 993 : 143;
|
||||||
|
|
||||||
|
$host2 || missing_option("--host2") ;
|
||||||
|
-$port2 = (defined($port2)) ? $port2 : 143;
|
||||||
|
+$port2 ||= defined $usessl ? 993 : 143;
|
||||||
|
|
||||||
|
-sub connect_imap {
|
||||||
|
- my($host, $port, $debugimap) = @_;
|
||||||
|
- my $imap = Mail::IMAPClient->new();
|
||||||
|
- $imap->Server($host);
|
||||||
|
- $imap->Port($port);
|
||||||
|
- $imap->Debug($debugimap);
|
||||||
|
- $imap->connect()
|
||||||
|
- or die "Can not open imap connection on [$host] : $@\n";
|
||||||
|
-}
|
||||||
|
+$authmech ||= $authusing ? 'PLAIN' : 'CRAM-MD5';
|
||||||
|
+
|
||||||
|
+my $from = connect_imap($host1, $port1, $timeout);
|
||||||
|
+print "From software : ", server_banner($from);
|
||||||
|
+print "From capability : ", join(" ", $from->capability()), "\n";
|
||||||
|
+
|
||||||
|
+my $to = connect_imap($host2, $port2, $timeout);
|
||||||
|
+print "To software : ", server_banner($to);
|
||||||
|
+print "To capability : ", join(" ", $to->capability()), "\n";
|
||||||
|
|
||||||
|
if ($justconnect) {
|
||||||
|
- my $from = ();
|
||||||
|
- my $to = ();
|
||||||
|
-
|
||||||
|
- $from = connect_imap($host1, $port1);
|
||||||
|
- print "From software : ", ($from->Report())[0];
|
||||||
|
- print "From capability : ", join(" ", $from->capability()), "\n";
|
||||||
|
- $to = connect_imap($host2, $port2);
|
||||||
|
- print "To software : ", ($to->Report())[0];
|
||||||
|
- print "To capability : ", join(" ", $to->capability()), "\n";
|
||||||
|
$from->logout();
|
||||||
|
$to->logout();
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
-
|
||||||
|
|
||||||
|
$user1 || missing_option("--user1");
|
||||||
|
$user2 || missing_option("--user2");
|
||||||
|
|
||||||
|
-$authmd5 = (defined($authmd5)) ? $authmd5 : 1;
|
||||||
|
-
|
||||||
|
$syncacls = (defined($syncacls)) ? $syncacls : 0;
|
||||||
|
$foldersizes = (defined($foldersizes)) ? $foldersizes : 1;
|
||||||
|
|
||||||
|
-$fastio1 = (defined($fastio1)) ? $fastio1 : 1;
|
||||||
|
-$fastio2 = (defined($fastio2)) ? $fastio2 : 1;
|
||||||
|
-
|
||||||
|
-
|
||||||
|
@useheader = ("ALL") unless (@useheader);
|
||||||
|
|
||||||
|
-print "From imap server [$host1] port [$port1] user [$user1]\n";
|
||||||
|
-print "To imap server [$host2] port [$port2] user [$user2]\n";
|
||||||
|
+if (defined $authusing) {
|
||||||
|
+ print "From [$user1\@$host1:$port1] authenticate as [$authusing]\n";
|
||||||
|
+ print "To [$user2\@$host2:$port2] authenticate as [$authusing]\n";
|
||||||
|
+} else {
|
||||||
|
+ print "From [$user1\@$host1:$port1]\n";
|
||||||
|
+ print "To [$user2\@$host2:$port2]\n";
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+sub ask_for_password {
|
||||||
|
+ my ($user, $host) = @_;
|
||||||
|
|
||||||
|
-$password1 || $passfile1 || do {
|
||||||
|
- print "What's the password for $user1\@$host1? ";
|
||||||
|
+ print "What's the password for $user\@$host? ";
|
||||||
|
ReadMode 2;
|
||||||
|
- $password1 = <>; chop $password1;
|
||||||
|
- printf "\n"; ReadMode 0;
|
||||||
|
-};
|
||||||
|
+ my $password = <>;
|
||||||
|
+ chomp $password;
|
||||||
|
+ printf "\n";
|
||||||
|
+ ReadMode 0;
|
||||||
|
+ return $password;
|
||||||
|
+}
|
||||||
|
|
||||||
|
+unless ($password1 || $passfile1) {
|
||||||
|
+ $password1 = ask_for_password($authusing || $user1, $host1);
|
||||||
|
+}
|
||||||
|
$password1 = (defined($passfile1)) ? firstline ($passfile1) : $password1;
|
||||||
|
|
||||||
|
-$password2 || $passfile2 || do {
|
||||||
|
- print "What's the password for $user2\@$host2? ";
|
||||||
|
- ReadMode 2;
|
||||||
|
- $password2 = <>; chop $password2;
|
||||||
|
- printf "\n"; ReadMode 0;
|
||||||
|
-};
|
||||||
|
+unless ($password2 || $passfile2) {
|
||||||
|
+ $password2 = $authusing ? $password1 : ask_for_password($user2, $host2);
|
||||||
|
+}
|
||||||
|
$password2 = (defined($passfile2)) ? firstline ($passfile2) : $password2;
|
||||||
|
|
||||||
|
-my $from = ();
|
||||||
|
-my $to = ();
|
||||||
|
-
|
||||||
|
-my $authmech = "CRAM-MD5";
|
||||||
|
-
|
||||||
|
-
|
||||||
|
$timestart = time();
|
||||||
|
$timebefore = $timestart;
|
||||||
|
|
||||||
|
-$fastio1 = 1;
|
||||||
|
-$fastio2 = 1;
|
||||||
|
-
|
||||||
|
$debugimap and print "From connection\n";
|
||||||
|
-$from = login_imap($host1, $port1, $user1, $password1, $debugimap, $timeout, $fastio1);
|
||||||
|
-
|
||||||
|
+$from = login_imap($from, $user1, $password1);
|
||||||
|
$debugimap and print "To connection\n";
|
||||||
|
-$to = login_imap($host2, $port2, $user2, $password2, $debugimap, $timeout, $fastio2);
|
||||||
|
+$to = login_imap($to, $user2, $password2);
|
||||||
|
|
||||||
|
# No history
|
||||||
|
$from->Clear(2);
|
||||||
|
@@ -518,69 +503,79 @@
|
||||||
|
$debug and print "From Buffer I/O : ", $from->Buffer(), "\n";
|
||||||
|
$debug and print "To Buffer I/O : ", $to->Buffer(), "\n";
|
||||||
|
|
||||||
|
-
|
||||||
|
|
||||||
|
-sub login_imap {
|
||||||
|
- my($host, $port, $user, $password,
|
||||||
|
- $debugimap, $timeout, $fastio) = @_;
|
||||||
|
- my $imap = Mail::IMAPClient->new();
|
||||||
|
+sub connect_imap {
|
||||||
|
+ my ($host, $port, $timeout) = @_;
|
||||||
|
+ my ($imap);
|
||||||
|
+ if ($usessl) {
|
||||||
|
+ my $ssl = new IO::Socket::SSL("$host:$port");
|
||||||
|
+ die "Error connecting to $host:$port: $@\n" unless $ssl;
|
||||||
|
+ $ssl->autoflush(1);
|
||||||
|
+
|
||||||
|
+ $imap = Mail::IMAPClient->new(
|
||||||
|
+ Socket => $ssl,
|
||||||
|
+ Server => $host,
|
||||||
|
+ );
|
||||||
|
+ } else {
|
||||||
|
+ $imap = Mail::IMAPClient->new();
|
||||||
|
+ }
|
||||||
|
$imap->Server($host);
|
||||||
|
$imap->Port($port);
|
||||||
|
- $imap->Fast_io($fastio);
|
||||||
|
$imap->Buffer($buffersize || 4096);
|
||||||
|
$imap->Uid(1);
|
||||||
|
$imap->Peek(1);
|
||||||
|
$imap->Debug($debugimap);
|
||||||
|
- $imap->connect()
|
||||||
|
- or die "Can not open imap connection on [$host] with user [$user] : $@\n";
|
||||||
|
+ if ($usessl) {
|
||||||
|
+ $imap->State(Mail::IMAPClient::Connected);
|
||||||
|
+ } else {
|
||||||
|
+ $imap->connect()
|
||||||
|
+ or die "Can not open imap connection on [$host]: $@\n";
|
||||||
|
+ }
|
||||||
|
+ if ($authusing && $authmech ne "PLAIN") {
|
||||||
|
+ print "ERROR: --authusing is only implemented with --authmech PLAIN\n";
|
||||||
|
+ } elsif ($authmech eq "LOGIN") {
|
||||||
|
+ # Default mode for Mail::IMAPClient, so don't do anything.
|
||||||
|
+ } elsif ($imap->has_capability("AUTH=$authmech")) {
|
||||||
|
+ $imap->Authmechanism($authmech);
|
||||||
|
+ $imap->Authcallback(\&plainauth) if $authmech eq "PLAIN";
|
||||||
|
+ } else {
|
||||||
|
+ printf("%s: no support for AUTHENTICATE %s, using LOGIN\n",
|
||||||
|
+ $imap->Server, $authmech);
|
||||||
|
+ }
|
||||||
|
if ($timeout) # whr (ESS/PRW)
|
||||||
|
{
|
||||||
|
$imap->Timeout($timeout);
|
||||||
|
print "Setting imap timeout to $timeout\n";
|
||||||
|
}
|
||||||
|
-
|
||||||
|
- $imap->User($user);
|
||||||
|
- $imap->Password($password);
|
||||||
|
- md5auth($imap);
|
||||||
|
- $imap->login() or die "Error login : [$host] with user [$user] : $@";
|
||||||
|
return($imap);
|
||||||
|
}
|
||||||
|
|
||||||
|
-
|
||||||
|
-sub md5auth() {
|
||||||
|
- my ($imap) = @_;
|
||||||
|
-
|
||||||
|
- unless ($authmd5) {
|
||||||
|
- print "$authmech not wanted by you\n";
|
||||||
|
- return;
|
||||||
|
- }
|
||||||
|
- if ($imap->has_capability($authmech)
|
||||||
|
- or $imap->has_capability("AUTH=$authmech")) {
|
||||||
|
- print "Server [", $imap->Server,
|
||||||
|
- "] has capability $authmech\n";
|
||||||
|
- }else{
|
||||||
|
- print "Server [", $imap->Server,
|
||||||
|
- "] has NOT capability $authmech\n";
|
||||||
|
- return;
|
||||||
|
- }
|
||||||
|
- #print "EE", $imap->Authmechanism(), "\n";
|
||||||
|
- if ($imap->Authmechanism($authmech)) {
|
||||||
|
- print "Using $authmech authentification\n";
|
||||||
|
- }else{
|
||||||
|
- $imap->Authmechanism(undef);
|
||||||
|
- print "Can NOT use $authmech authentification, using plain\n";
|
||||||
|
+sub server_banner {
|
||||||
|
+ my $imap = shift;
|
||||||
|
+ for my $line ($imap->Results()) {
|
||||||
|
+ return $line if $line =~ /^\* (OK|NO|BAD)/;
|
||||||
|
}
|
||||||
|
- return;
|
||||||
|
+ return "No banner\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
+sub login_imap {
|
||||||
|
+ my ($imap, $user, $password) = @_;
|
||||||
|
|
||||||
|
+ $imap->User($user);
|
||||||
|
+ $imap->Password($password);
|
||||||
|
+ $imap->login()
|
||||||
|
+ or die "Error login: [$imap->{Server}] with user [$user]: $@\n";
|
||||||
|
+ return($imap);
|
||||||
|
+}
|
||||||
|
|
||||||
|
-
|
||||||
|
-print "From software : ", ($from->Report())[0];
|
||||||
|
-print "To software : ", ($to->Report())[0];
|
||||||
|
-
|
||||||
|
-print "From capability : ", join(" ", $from->capability()), "\n";
|
||||||
|
-print "To capability : ", join(" ", $to->capability()), "\n";
|
||||||
|
+sub plainauth() {
|
||||||
|
+ my $code = shift;
|
||||||
|
+ my $imap = shift;
|
||||||
|
+
|
||||||
|
+ my $string = sprintf("%s\x00%s\x00%s", $imap->User,
|
||||||
|
+ $authusing || $imap->User, $imap->Password);
|
||||||
|
+ return encode_base64("$string");
|
||||||
|
+}
|
||||||
|
|
||||||
|
die unless $from->IsAuthenticated();
|
||||||
|
die unless $to->IsAuthenticated();
|
||||||
|
@@ -601,7 +596,7 @@
|
||||||
|
@f_folders = sort keys (%fs_folders);
|
||||||
|
}else {
|
||||||
|
# no option, all folders
|
||||||
|
- @f_folders = sort $from->folders();
|
||||||
|
+ @f_folders = sort $from->folders($prefix1);
|
||||||
|
# consider (optional) includes and excludes
|
||||||
|
if ($include) {
|
||||||
|
@f_folders = grep /$include/,@f_folders;
|
||||||
|
@@ -615,22 +610,33 @@
|
||||||
|
|
||||||
|
@t_folders = sort @{$to->folders()};
|
||||||
|
|
||||||
|
-my($f_sep,$t_sep);
|
||||||
|
# what are the private folders separators for each server ?
|
||||||
|
+my $f_sep = get_separator($from, $sep1, "--sep1");
|
||||||
|
+my $f_prefix = get_prefix($from, $prefix1, "--prefix1");
|
||||||
|
|
||||||
|
+if (@t_folders == 0) {
|
||||||
|
+ if ($authusing) {
|
||||||
|
+ # We assume we're allowed to create new users.
|
||||||
|
+ # We may need to make the "user." prefix configurable
|
||||||
|
+ unless ($dry || $to->create("user.$user2")) {
|
||||||
|
+ print STDERR "Couldn't create user.$user2 on $host2",
|
||||||
|
+ $to->LastError, "\n";
|
||||||
|
+ exit(1);
|
||||||
|
+ }
|
||||||
|
+ } else {
|
||||||
|
+ print "$user2 does not exist on $host2\n";
|
||||||
|
+ exit(1);
|
||||||
|
+ }
|
||||||
|
+}
|
||||||
|
|
||||||
|
-$debug and print "Getting separators\n";
|
||||||
|
-$f_sep = get_separator($from, $sep1, "--sep1");
|
||||||
|
-$t_sep = get_separator($to, $sep2, "--sep2");
|
||||||
|
+my $t_sep = get_separator($to, $sep2, "--sep2");
|
||||||
|
+my $t_prefix = get_prefix($to, $prefix2, "--prefix2");
|
||||||
|
|
||||||
|
#my $f_namespace = $from->namespace();
|
||||||
|
#my $t_namespace = $to->namespace();
|
||||||
|
#$debug and print "From namespace:\n", Data::Dumper->Dump([$f_namespace]);
|
||||||
|
#$debug and print "To namespace:\n", Data::Dumper->Dump([$t_namespace]);
|
||||||
|
|
||||||
|
-my($f_prefix,$t_prefix);
|
||||||
|
-$f_prefix = get_prefix($from, $prefix1, "--prefix1");
|
||||||
|
-$t_prefix = get_prefix($to, $prefix2, "--prefix2");
|
||||||
|
|
||||||
|
sub get_prefix {
|
||||||
|
my($imap, $prefix_in, $prefix_opt) = @_;
|
||||||
|
@@ -691,7 +697,7 @@
|
||||||
|
my $tot = 0;
|
||||||
|
my $tmess = 0;
|
||||||
|
my @folders = @{$folders_r};
|
||||||
|
- print "++++ Calculating sizes ++++\n";
|
||||||
|
+ print "++++ Calculating sizes ++++\n" if $verbose;
|
||||||
|
foreach my $folder (@folders) {
|
||||||
|
my $stot = 0;
|
||||||
|
my $smess = 0;
|
||||||
|
@@ -881,7 +887,8 @@
|
||||||
|
my $f_heads = $from->parse_headers($from->Range([@f_msgs]),@useheader)
|
||||||
|
if (@f_msgs) ;
|
||||||
|
$debug and print "Time headers: ", timenext(), " s\n";
|
||||||
|
- my $f_size = $from->fetch_hash("RFC822.SIZE") if (@f_msgs);
|
||||||
|
+ my $f_size = $from->fetch_hash("FLAGS", "INTERNALDATE", "RFC822.SIZE")
|
||||||
|
+ if (@f_msgs);
|
||||||
|
$debug and print "Time sizes : ", timenext(), " s\n";
|
||||||
|
#my $f_flags = $from->flags(@f_msgs) ;
|
||||||
|
#print "Time flags : ", timenext(), " s\n";
|
||||||
|
@@ -909,7 +916,7 @@
|
||||||
|
$debug and print "Time headers: ", timenext(), " s\n";
|
||||||
|
#exit;
|
||||||
|
|
||||||
|
- print "++++ Verifying [$f_fold] -> [$t_fold] ++++\n";
|
||||||
|
+ print "++++ Synchronizing [$f_fold] -> [$t_fold] ++++\n";
|
||||||
|
# messages in "from" that are not good in "to"
|
||||||
|
|
||||||
|
my @f_hash_keys_sorted_by_uid
|
||||||
|
@@ -928,9 +935,11 @@
|
||||||
|
}
|
||||||
|
$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";
|
||||||
|
+ print "+ NO msg #$f_msg [$m_id] in $t_fold\n"
|
||||||
|
+ if $verbose;
|
||||||
|
# copy
|
||||||
|
- print "+ Copying msg #$f_msg:$f_size to folder $t_fold\n";
|
||||||
|
+ print "+ Copying msg #$f_msg:$f_size to folder $t_fold\n"
|
||||||
|
+ if $verbose;
|
||||||
|
my $string = $from->message_string($f_msg);
|
||||||
|
foreach my $regexmess (@regexmess) {
|
||||||
|
$debug and print "eval \$string =~ $regexmess\n";
|
||||||
|
@@ -939,33 +948,18 @@
|
||||||
|
$debug and print "F message content begin next line\n",
|
||||||
|
$string,
|
||||||
|
"F message content ended on previous line\n";
|
||||||
|
- my $d = "";
|
||||||
|
- if ($syncinternaldates) {
|
||||||
|
- $d = $from->internaldate($f_msg);
|
||||||
|
- $d = "\"$d\"";
|
||||||
|
- $debug and print "internal date from 1: [$d]\n";
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- 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)});
|
||||||
|
|
||||||
|
+ my $flags_f = $f_hash{$m_id}{'F'} || "";
|
||||||
|
# RFC 2060 : This flag can not be altered by the client
|
||||||
|
$flags_f =~ s@\\Recent@@g;
|
||||||
|
|
||||||
|
my $new_id;
|
||||||
|
- print "flags from : [$flags_f][$d]\n";
|
||||||
|
+ my $indate = $f_hash{$m_id}{'D'};
|
||||||
|
+ print "flags from : [$flags_f][$indate]\n" if $verbose;
|
||||||
|
unless ($dry) {
|
||||||
|
- unless($new_id = $to->append_string($t_fold,$string, $flags_f, $d)){
|
||||||
|
+ $new_id = $to->append_string($t_fold, $string,
|
||||||
|
+ $flags_f, $indate);
|
||||||
|
+ unless($new_id){
|
||||||
|
warn "Couldn't append msg #$f_msg (Subject:[".$from->subject($f_msg)."]) to folder $t_fold: ",
|
||||||
|
$to->LastError, "\n";
|
||||||
|
$error++;
|
||||||
|
@@ -976,7 +970,7 @@
|
||||||
|
# good
|
||||||
|
# $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";
|
||||||
|
+ print "Copied msg id [$f_msg] to folder $t_fold msg id [$new_id]\n" if $verbose;
|
||||||
|
$mess_size_total_trans += $f_size;
|
||||||
|
$mess_trans += 1;
|
||||||
|
}
|
||||||
|
@@ -1116,17 +1110,19 @@
|
||||||
|
my $opt_ret = GetOptions(
|
||||||
|
"debug!" => \$debug,
|
||||||
|
"debugimap!" => \$debugimap,
|
||||||
|
+ "verbose!" => \$verbose,
|
||||||
|
"host1=s" => \$host1,
|
||||||
|
"host2=s" => \$host2,
|
||||||
|
"port1=i" => \$port1,
|
||||||
|
"port2=i" => \$port2,
|
||||||
|
"user1=s" => \$user1,
|
||||||
|
"user2=s" => \$user2,
|
||||||
|
+ "authusing=s" => \$authusing,
|
||||||
|
+ "authmech=s" => \$authmech,
|
||||||
|
"password1=s" => \$password1,
|
||||||
|
"password2=s" => \$password2,
|
||||||
|
"passfile1=s" => \$passfile1,
|
||||||
|
"passfile2=s" => \$passfile2,
|
||||||
|
- "authmd5!" => \$authmd5,
|
||||||
|
"sep1=s" => \$sep1,
|
||||||
|
"sep2=s" => \$sep2,
|
||||||
|
"folder=s" => \@folder,
|
||||||
|
@@ -1137,7 +1133,6 @@
|
||||||
|
"regextrans2=s" => \@regextrans2,
|
||||||
|
"regexmess=s" => \@regexmess,
|
||||||
|
"delete!" => \$delete,
|
||||||
|
- "syncinternaldates!" => \$syncinternaldates,
|
||||||
|
"syncacls!" => \$syncacls,
|
||||||
|
"maxsize=i" => \$maxsize,
|
||||||
|
"maxage=i" => \$maxage,
|
||||||
|
@@ -1160,8 +1155,7 @@
|
||||||
|
"skipheader=s" => \$skipheader,
|
||||||
|
"useheader=s" => \@useheader,
|
||||||
|
"skipsize!" => \$skipsize,
|
||||||
|
- "fastio1!" => \$fastio1,
|
||||||
|
- "fastio2!" => \$fastio2,
|
||||||
|
+ "ssl!" => \$usessl
|
||||||
|
);
|
||||||
|
|
||||||
|
$debug and print "get options: [$opt_ret]\n";
|
||||||
|
@@ -1221,6 +1215,8 @@
|
||||||
|
}
|
||||||
|
$s_hash->{"$key"}{'5'} = $m_md5;
|
||||||
|
$s_hash->{"$key"}{'s'} = $size;
|
||||||
|
+ $s_hash->{"$key"}{'D'} = $s_size->{$m_uid}->{"INTERNALDATE"};
|
||||||
|
+ $s_hash->{"$key"}{'F'} = $s_size->{$m_uid}->{"FLAGS"};
|
||||||
|
$s_hash->{"$key"}{'m'} = $m_uid;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -1253,10 +1249,10 @@
|
||||||
|
--host2 <string> : "destination" imap server. Mandatory.
|
||||||
|
--port2 <int> : port to connect. Default is 143.
|
||||||
|
--user2 <string> : user to login. Mandatory.
|
||||||
|
+--authusing <string> : user to auth with (when running on behalf of another)
|
||||||
|
+--authmech <string> : auth mechanism to use (e.g. PLAIN, LOGIN, CRAM-MD5...)
|
||||||
|
--password2 <string> : password for the user2. Dangerous, use --passfile2
|
||||||
|
--passfile2 <string> : password file for the user2. Contains the password.
|
||||||
|
---noauthmd5 : don't use MD5 authentification.
|
||||||
|
---authmd5 : use MD5 authentification.
|
||||||
|
--folder <string> : sync only this folder.
|
||||||
|
--folder <string> : and this one.
|
||||||
|
--folder <string> : and this one, etc.
|
||||||
|
@@ -1300,7 +1296,6 @@
|
||||||
|
it will change in future releases.
|
||||||
|
--expunge1 : expunge messages on source account.
|
||||||
|
--expunge2 : expunge messages on target account.
|
||||||
|
---syncinternaldates : sets the internal dates on host2 same as host1
|
||||||
|
--buffersize <int> : sets the size of a block of I/O.
|
||||||
|
--maxsize <int> : skip messages larger than <int> bytes
|
||||||
|
--maxage <int> : skip messages older than <int> days.
|
||||||
|
@@ -1332,14 +1327,14 @@
|
||||||
|
--nosyncacls : Does not synchronize acls. This is the default.
|
||||||
|
--debug : debug mode.
|
||||||
|
--debugimap : imap debug mode.
|
||||||
|
---version : print sotfware version.
|
||||||
|
+--verbose : print information about each message transferred
|
||||||
|
+--version : print software version.
|
||||||
|
--justconnect : just connect to both servers and print useful
|
||||||
|
information. Need only --host1 and --host2 options.
|
||||||
|
--justfolders : just do things about folders (ignore messages).
|
||||||
|
--fast : be faster (does not sync flags).
|
||||||
|
---nofastio1 : don't use fastio with the "from" server.
|
||||||
|
---nofastio2 : don't use fastio with the "destination" server.
|
||||||
|
--timeout <int> : imap connect timeout.
|
||||||
|
+--ssl : use SSL connections.
|
||||||
|
--help : print this.
|
||||||
|
|
||||||
|
Example: to synchronise imap account "foo" on "imap.truc.org"
|
Loading…
Reference in New Issue
Block a user