This commit is contained in:
Nick Bebout 2012-09-11 20:50:53 -05:00
parent c08a56e486
commit 1e03db551f
58 changed files with 790 additions and 435 deletions

View file

@ -1,17 +1,33 @@
RCS file: RCS/imapsync,v RCS file: RCS/imapsync,v
Working file: imapsync Working file: imapsync
head: 1.504 head: 1.508
branch: branch:
locks: strict locks: strict
gilles: 1.504 gilles: 1.508
access list: access list:
symbolic names: symbolic names:
keyword substitution: kv keyword substitution: kv
total revisions: 504; selected revisions: 504 total revisions: 508; selected revisions: 508
description: description:
---------------------------- ----------------------------
revision 1.504 locked by: gilles; revision 1.508 locked by: gilles;
date: 2012/09/10 21:10:13; author: gilles; state: Exp; lines: +81 -17
Added ETA after each copy. Estimated Time of Arrival.
----------------------------
revision 1.507
date: 2012/09/09 12:57:44; author: gilles; state: Exp; lines: +20 -12
Bugfix. Previous fix about characters *|?:"<> in cache path was not complete.
----------------------------
revision 1.506
date: 2012/09/07 14:51:00; author: gilles; state: Exp; lines: +10 -7
Option. Added --noexpungeaftereach to speedup --delete --expunge from Gmail.
----------------------------
revision 1.505
date: 2012/09/07 10:40:55; author: gilles; state: Exp; lines: +10 -10
Usability. Added Host1 or Host2 before "Nb messages" "Total size" with --foldersiszes
----------------------------
revision 1.504
date: 2012/08/28 13:10:26; author: gilles; state: Exp; lines: +10 -9 date: 2012/08/28 13:10:26; author: gilles; state: Exp; lines: +10 -9
Bugfix. sentsince sentbefore in int seconds. Bugfix. sentsince sentbefore in int seconds.
---------------------------- ----------------------------

20
FAQ
View file

@ -1,5 +1,5 @@
#!/bin/cat #!/bin/cat
# $Id: FAQ,v 1.114 2012/07/19 09:42:13 gilles Exp gilles $ # $Id: FAQ,v 1.116 2012/09/11 21:00:06 gilles Exp gilles $
+------------------+ +------------------+
| FAQ for imapsync | | FAQ for imapsync |
@ -262,13 +262,13 @@ R. - Download latest Mail::IMAPClient 3.xx at
- run imapsync with perl and -I option tailing to use the perl - run imapsync with perl and -I option tailing to use the perl
module Mail-IMAPClient-3.xx. Example: module Mail-IMAPClient-3.xx. Example:
perl -I./Mail-IMAPClient-3.31/lib ./imapsync ... perl -I./Mail-IMAPClient-3.32/lib ./imapsync ...
or if imapsync is in directory /path/ or if imapsync is in directory /path/
perl -I./Mail-IMAPClient-3.31/lib /path/imapsync ... perl -I./Mail-IMAPClient-3.32/lib /path/imapsync ...
- Look at the script named i3 in the tarball, it can be used to - Look at the script named i3 in the tarball, it can be used to
run imapsync with included Mail-IMAPClient-3.31/ wherever you run imapsync with included Mail-IMAPClient-3.32/ wherever you
unpacked the imapsync tarball unpacked the imapsync tarball
======================================================================= =======================================================================
@ -1370,15 +1370,16 @@ R. GroupWise 7 seems buggy. Apply GroupWise 7 support pack 1
Q. Migrating from David Tobit V10 Q. Migrating from David Tobit V10
R. Use the following options: R. Use the following options:
imapsync ... --prefix1 "" --sep1 / --idatefromheader ^ imapsync ... --prefix1 "" --sep1 / --idatefromheader ^
--nofoldersizes --useuid --nofoldersizes --useuid --nocheckmessageexists
=======================================================================
======================================================================= =======================================================================
Q. Migrating from David Tobit V8 Q. Migrating from David Tobit V8
First try above V10 solution since improvments have been made
to support Tobit.
R. Use the following options : R. Use the following options :
imapsync ... --prefix1 INBOX. --sep1 / --subscribe --subscribed imapsync ... --prefix1 INBOX. --sep1 / --subscribe --subscribed
@ -1386,6 +1387,9 @@ imapsync ... --prefix1 INBOX. --sep1 / --subscribe --subscribed
Q. Migrating from Tobit David Server 6 Q. Migrating from Tobit David Server 6
("DvISE Mail Access Server MA-6.60a (0118)") ("DvISE Mail Access Server MA-6.60a (0118)")
First try above V10 solution since improvments have been made
to support Tobit.
R. Look at the discussion: R. Look at the discussion:
http://www.linux-france.org/prj/imapsync_list/msg00582.html http://www.linux-france.org/prj/imapsync_list/msg00582.html
http://www.linux-france.org/prj/imapsync_list/threads.html#00582 http://www.linux-france.org/prj/imapsync_list/threads.html#00582

30
INSTALL
View file

@ -1,4 +1,4 @@
# $Id: INSTALL,v 1.25 2012/07/19 05:57:14 gilles Exp gilles $ # $Id: INSTALL,v 1.26 2012/09/11 21:00:06 gilles Exp gilles $
# #
# INSTALL file for imapsync # INSTALL file for imapsync
# imapsync : IMAP sync or copy tool. # imapsync : IMAP sync or copy tool.
@ -76,19 +76,20 @@ Here is some individual module help:
perl -mMail::IMAPClient -e 'print $Mail::IMAPClient::VERSION, "\n"' perl -mMail::IMAPClient -e 'print $Mail::IMAPClient::VERSION, "\n"'
New Mail-IMAPClient-3.xx works now very well with imapsync, New Mail-IMAPClient-3.xx works now very well with imapsync,
better than Mail-IMAPClient-2.2.9 with memory and other things, better than old Mail-IMAPClient-2.2.9, with memory and other things.
at least with Mail-IMAPClient-3.25 (previous may bug). Use at least Mail-IMAPClient-3.25 (previous may bug).
Don't hesitate to use latest Mail-IMAPClient-3.xx Don't hesitate to use latest Mail-IMAPClient-3.xx (3.xx >= 3.32 at the time
of this writing)
Look at the script named i3 in the tarball, it can be used to Look at the script named i3 in the tarball, it can be used to
run imapsync with included Mail-IMAPClient-3.31/ wherever you run imapsync with included Mail-IMAPClient-3.32/ wherever you
unpacked the imapsync tarball. unpacked the imapsync tarball.
- Perl Digest::MD5 module. - Perl Digest::MD5 module.
try: try:
perl -mDigest::MD5 perl -mDigest::MD5 -e ""
http://search.cpan.org/ http://search.cpan.org/
http://search.cpan.org/~gaas/Digest-MD5-2.52/ http://search.cpan.org/~gaas/Digest-MD5-2.52/
@ -97,27 +98,31 @@ Here is some individual module help:
I use 2.39 (Ubuntu package) I use 2.39 (Ubuntu package)
- Term::ReadKey - Term::ReadKey
perl -mTerm::ReadKey -e '' perl -mTerm::ReadKey -e ""
- IO::Socket::SSL - IO::Socket::SSL
perl -mIO::Socket::SSL -e '' perl -mIO::Socket::SSL -e ""
- File::Spec - File::Spec
perl -mFile::Spec -e '' perl -mFile::Spec -e ""
- File::Path - File::Path
perl -mFile::Path -e '' perl -mFile::Path -e ""
- Perl Digest::HMAC_MD5 module - Perl Digest::HMAC_MD5 module
Good for non plain text password over network. Good for non plain text password over network.
perl -mDigest::HMAC_MD5 -e ""
- Perl Authen::NTLM - Perl Authen::NTLM
perl -mAuthen::NTLM -e '' perl -mAuthen::NTLM -e ""
- Perl Time::HiRes
perl -mTime::HiRes -e ""
Test everything in one command: Test everything in one command:
perl -mMail::IMAPClient -mDigest::MD5 -mTerm::ReadKey -mIO::Socket::SSL \ perl -mMail::IMAPClient -mDigest::MD5 -mTerm::ReadKey -mIO::Socket::SSL \
-mFile::Spec -mDigest::HMAC_MD5 -mAuthen::NTLM -e '' -mFile::Spec -mDigest::HMAC_MD5 -mAuthen::NTLM -e -mTime::HiRes ''
You can install easily those Perl modules in latest release via the You can install easily those Perl modules in latest release via the
following commands (with root permissions) following commands (with root permissions)
@ -129,6 +134,7 @@ following commands (with root permissions)
perl -MCPAN -e 'install File::Spec' perl -MCPAN -e 'install File::Spec'
perl -MCPAN -e 'install Digest::HMAC_MD5' perl -MCPAN -e 'install Digest::HMAC_MD5'
perl -MCPAN -e 'install Authen::NTLM' perl -MCPAN -e 'install Authen::NTLM'
perl -MCPAN -e 'install Time::HiRes'
You can install them easily too by using the standard install You can install them easily too by using the standard install
command on your system if the packages have been made on it command on your system if the packages have been made on it

View file

@ -1,5 +1,5 @@
# $Id: Makefile,v 1.103 2012/08/29 10:24:17 gilles Exp gilles $ # $Id: Makefile,v 1.107 2012/09/11 21:00:06 gilles Exp gilles $
.PHONY: help usage all .PHONY: help usage all
@ -32,7 +32,7 @@ VERSION_EXE=$(shell cat ./VERSION_EXE)
HELLO=$(shell date;uname -a) HELLO=$(shell date;uname -a)
IMAPClient_2xx=./W/Mail-IMAPClient-2.2.9 IMAPClient_2xx=./W/Mail-IMAPClient-2.2.9
IMAPClient_3xx=./W/Mail-IMAPClient-3.31/lib IMAPClient_3xx=./W/Mail-IMAPClient-3.32/lib
IMAPClient=$(IMAPClient_3xx) IMAPClient=$(IMAPClient_3xx)
hello: hello:
@ -264,20 +264,24 @@ ksa:
rsync -avHz --delete \ rsync -avHz --delete \
. imapsync@ks.lamiral.info:public_html/imapsync/ . imapsync@ks.lamiral.info:public_html/imapsync/
publish: upload_ks ks publish: upload_ks ks ml
PUBLIC_FILES = ./ChangeLog ./COPYING ./CREDITS ./FAQ \ PUBLIC_FILES = ./ChangeLog ./COPYING ./CREDITS ./FAQ \
./index.shtml ./INSTALL \ ./index.shtml ./INSTALL \
./VERSION ./VERSION_EXE \
./README ./TODO ./README ./TODO
PUBLIC_FILES_W = ./W/style.css \ PUBLIC_FILES_W = ./W/style.css \
./TIME \ ./W/TIME \
./VERSION ./VERSION_EXE \
./W/paypal.shtml ./W/paypal_return.shtml ./W/paypal_return_support.shtml ./W/paypal.shtml ./W/paypal_return.shtml ./W/paypal_return_support.shtml
PUBLIC_FILES_IMAGES = ./W/images/logo_imapsync.png ./W/images/logo_imapsync_s.png PUBLIC_FILES_IMAGES = ./W/images/logo_imapsync.png ./W/images/logo_imapsync_s.png
ml:
m4 -P W/ml_announce.in | mutt -H-
mailq
upload_ks: ci upload_ks: ci
rsync -lptvHzP $(PUBLIC_FILES) \ rsync -lptvHzP $(PUBLIC_FILES) \
@ -303,13 +307,10 @@ upload_lfo:
/home/gilles/public_html/www.linux-france.org/html/prj/imapsync/.htaccess /home/gilles/public_html/www.linux-france.org/html/prj/imapsync/.htaccess
sh ~/memo/lfo-rsync sh ~/memo/lfo-rsync
upload_index: index.shtml FAQ paypal.shtml upload_index: index.shtml FAQ
validate --verbose index.shtml paypal.shtml validate --verbose index.shtml
rcsdiff index.shtml paypal.shtml FAQ COPYING rcsdiff index.shtml FAQ COPYING
rsync -avH index.shtml FAQ paypal.shtml COPYING root@ks.lamiral.info:/var/www/imapsync/ rsync -avH index.shtml FAQ COPYING root@ks.lamiral.info:/var/www/imapsync/
rsync -avH index.shtml FAQ paypal.shtml COPYING \
../../public_html/www.linux-france.org/html/prj/imapsync/
sh $(HOME)/memo/lfo-rsync
niouze_lfo : niouze_lfo :
echo "CORRECT ME: . ./memo && lfo_announce" echo "CORRECT ME: . ./memo && lfo_announce"

4
README
View file

@ -3,7 +3,7 @@ NAME
Synchronise mailboxes between two imap servers. Good at IMAP migration. Synchronise mailboxes between two imap servers. Good at IMAP migration.
More than 44 different IMAP server softwares supported with success. More than 44 different IMAP server softwares supported with success.
$Revision: 1.504 $ $Revision: 1.508 $
SYNOPSIS SYNOPSIS
To synchronise imap account "foo" on "imap.truc.org" to imap account To synchronise imap account "foo" on "imap.truc.org" to imap account
@ -440,5 +440,5 @@ SIMILAR SOFTWARES
Feedback (good or bad) will often be welcome. Feedback (good or bad) will often be welcome.
$Id: imapsync,v 1.504 2012/08/28 13:10:26 gilles Exp gilles $ $Id: imapsync,v 1.508 2012/09/10 21:10:13 gilles Exp gilles $

54
TODO
View file

@ -1,5 +1,5 @@
#!/bin/cat #!/bin/cat
# $Id: TODO,v 1.112 2012/07/19 09:41:54 gilles Exp gilles $ # $Id: TODO,v 1.113 2012/09/11 20:58:32 gilles Exp gilles $
TODO file for imapsync TODO file for imapsync
---------------------- ----------------------
@ -31,14 +31,7 @@ Add a FAQ entry about long path over than 260 character on Win32.
Fix long path over than 260 character on Win32. Fix long path over than 260 character on Win32.
Think about Digest::SHA or Digest::SHA::PurePerl. Think about Digest::SHA or Digest::SHA::PurePerl.
Think about a file database like DBM instead.
Try to use imapsync with cygwin.
Add an option to solve syncing Sent folder when no good header
are available:
http://www.linux-france.org/prj/imapsync_list/msg01151.html
http://www.linux-france.org/prj/imapsync_list/msg01158.html
Find a way to avoid passwords in --debugimap unless needed. Find a way to avoid passwords in --debugimap unless needed.
@ -101,19 +94,6 @@ Fix bug "not possible to use space in the imap password"
Add kerberos authentification Add kerberos authentification
Add a --skipheaderinfolder option
Fix this:
> - Erreur avec la traditionnelle différence entre Windows
> et Linux sur les retour-chariots : le calcul de la
> longueur du message ou des entêtes à envoyer au serveur
> cible n'est pas bon sur une machine Windows.
> Ci-dessous la modif :
>
> # No NL Count on Windows my $length = ( -s $file ) + $bare_nl_count;
> my $length = ( -s $file );
I wonder if it is Windows or the imap server used.
Add stdin/stdout filter before transfer: Add stdin/stdout filter before transfer:
"Now i asked me, how to modify your perl program to work with "Now i asked me, how to modify your perl program to work with
@ -152,9 +132,6 @@ Add --verbose from Kjetil jumbo patch.
Read the IMAP RFC http://www.faqs.org/rfcs/rfc3501.html Read the IMAP RFC http://www.faqs.org/rfcs/rfc3501.html
Add debian packaging in the Makefile.
Write to the debian maintener about that.
Interface with external software like procmail Interface with external software like procmail
Read: Read:
@ -165,6 +142,33 @@ http://asg.web.cmu.edu/cyrus/download/imapd/altnamespace.html
=========================================================================== ===========================================================================
DONE. Not donse since useless now (--useuid)
Add a --skipheaderinfolder option
DONE. Not fixed since only reported once a long time ago.
Fix this:
> - Erreur avec la traditionnelle différence entre Windows
> et Linux sur les retour-chariots : le calcul de la
> longueur du message ou des entêtes à envoyer au serveur
> cible n'est pas bon sur une machine Windows.
> Ci-dessous la modif :
>
> # No NL Count on Windows my $length = ( -s $file ) + $bare_nl_count;
> my $length = ( -s $file );
I wonder if it is Windows or the imap server used.
DONE. No Debian package anymore.
Add debian packaging in the Makefile.
Write to the debian maintener about that.
DONE with --addheader
Add an option to solve syncing Sent folder when no good header
are available:
http://www.linux-france.org/prj/imapsync_list/msg01151.html
http://www.linux-france.org/prj/imapsync_list/msg01158.html
DONE. Add a note about DONE. Add a note about
"One other thing: You might want to warn idiots like me, that if your "One other thing: You might want to warn idiots like me, that if your
cache resides on a filesystem with a limited number of inodes such as cache resides on a filesystem with a limited number of inodes such as

View file

@ -1 +1 @@
1.504 1.508

View file

@ -1 +1 @@
1.504 1.508

View file

@ -152,3 +152,7 @@
1346160945 END 1.504 : mardi 28 août 2012, 15:35:45 (UTC+0200) 1346160945 END 1.504 : mardi 28 août 2012, 15:35:45 (UTC+0200)
1346241775 BEGIN 1.504 : mercredi 29 août 2012, 14:02:55 (UTC+0200) 1346241775 BEGIN 1.504 : mercredi 29 août 2012, 14:02:55 (UTC+0200)
1346242932 END 1.504 : mercredi 29 août 2012, 14:22:12 (UTC+0200) 1346242932 END 1.504 : mercredi 29 août 2012, 14:22:12 (UTC+0200)
1347195553 BEGIN 1.507 : dimanche 9 septembre 2012, 14:59:13 (UTC+0200)
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)

View file

@ -5,6 +5,27 @@ Changes from 2.99_01 to 3.16 made by Mark Overmeer
Changes from 0.09 to 2.99_01 made by David Kernen Changes from 0.09 to 2.99_01 made by David Kernen
- Potential compatibility issues from 3.17+ highlighted with '*' - Potential compatibility issues from 3.17+ highlighted with '*'
version 3.32: Fri, Aug 10, 2012 4:43:24 PM
- document RFC2087 quota related calls
[Mathias Reitinger] documentation request
- rt.cpan.org#78474: idle/idle_data documentation error
[Dima Kogan]
- Quote()/Massage() now uses literals for non ascii data
[Mathias Reitinger] reported issues with utf8 data in password
- use Quote()/Massage() consistently now in:
login() proxyauth() deleteacl() setacl() listrights() rename()
- documented deleteacl() and other minor pod cleanup
- ran Mail::IMAPClient::BodyStructure through perltidy
- update year in README/pod to 2012
- rt.cpan.org#74733: Fails with Parse::RecDescent >= 1.966_002
rt.cpan.org#74593: Recent changes break Module::ExtractUse and ...
[ANDK, TEAM, SREZIC, NBEBOUT at CPAN and nine from detonation]
- Makefile.PL avoid buggy Parse::RecDescent 1.966_002 until 1.967_009
- rt.cpan.org#76989: Mail::IMAPClient::BodyStructure usage/docs
[Pierluigi Frullani]
- fix incorrect documentation on new()
- lots of doc verbiage updates
version 3.31: Mon, Mar 19, 2012 11:11:11 AM version 3.31: Mon, Mar 19, 2012 11:11:11 AM
- rt.cpan.org#74799: Support for partial data responses in fetch_hash - rt.cpan.org#74799: Support for partial data responses in fetch_hash
[Philip Garrett] [Philip Garrett]

View file

@ -1,6 +1,6 @@
--- #YAML:1.0 --- #YAML:1.0
name: Mail-IMAPClient name: Mail-IMAPClient
version: 3.31 version: 3.32
abstract: IMAP4 client library abstract: IMAP4 client library
author: author:
- Phil Pearl (Lobbes) <phil@zimbra.com> - Phil Pearl (Lobbes) <phil@zimbra.com>
@ -28,7 +28,7 @@ no_index:
directory: directory:
- t - t
- inc - inc
generated_by: ExtUtils::MakeMaker version 6.55_02 generated_by: ExtUtils::MakeMaker version 6.57_05
meta-spec: meta-spec:
url: http://module-build.sourceforge.net/META-spec-v1.4.html url: http://module-build.sourceforge.net/META-spec-v1.4.html
version: 1.4 version: 1.4

View file

@ -37,6 +37,22 @@ MSG
sleep 3; sleep 3;
} }
# HACK: die on broken Parse::RecDescent 1.966002 through 1.967009
# - rt.cpan.org#74593: Recent changes break Module::ExtractUse and ...
# - rt.cpan.org#74733: Fails with Parse::RecDescent >= 1.966_002
do {
eval { require version; require Parse::RecDescent; };
unless ($@) {
my $found = version->parse( Parse::RecDescent->VERSION() );
my $broke = version->parse("1.966002");
my $fixed = version->parse("1.967009");
if ( $found < $fixed and $found >= $broke ) {
die("Found broken Parse::RecDescent $found in your environment.\n",
"Please upgrade to version $fixed or greater.\n");
}
}
};
WriteMakefile( WriteMakefile(
NAME => 'Mail::IMAPClient', NAME => 'Mail::IMAPClient',
AUTHOR => 'Phil Pearl (Lobbes) <phil@zimbra.com>', AUTHOR => 'Phil Pearl (Lobbes) <phil@zimbra.com>',

View file

@ -64,7 +64,7 @@ COPYRIGHT AND LICENSE
===================== =====================
Copyright (C) 1999-2003 The Kernen Group, Inc. Copyright (C) 1999-2003 The Kernen Group, Inc.
Copyright (C) 2007-2009 Mark Overmeer Copyright (C) 2007-2009 Mark Overmeer
Copyright (C) 2010-2011 Phil Pearl (Lobbes) Copyright (C) 2010-2012 Phil Pearl (Lobbes)
All rights reserved. All rights reserved.
This library is free software; you can redistribute it and/or modify This library is free software; you can redistribute it and/or modify

View file

@ -7,7 +7,7 @@ use strict;
use warnings; use warnings;
package Mail::IMAPClient; package Mail::IMAPClient;
our $VERSION = '3.31'; our $VERSION = '3.32';
use Mail::IMAPClient::MessageSet; use Mail::IMAPClient::MessageSet;
@ -546,20 +546,15 @@ sub login {
or return undef; or return undef;
} }
else { else {
my $user = $self->User;
my $passwd = $self->Password; my $passwd = $self->Password;
my $id = $self->User;
return undef unless ( defined($passwd) and defined($id) ); return undef unless ( defined($passwd) and defined($user) );
# BUG: should use Quote() with $passwd and $id $user = ( $user eq "" ) ? qq("") : $self->Quote($user);
if ( $passwd eq "" or $passwd =~ m/\W/ ) { $passwd = ( $passwd eq "" ) ? qq("") : $self->Quote($passwd);
$passwd =~ s/(["\\])/\\$1/g;
$passwd = qq("$passwd");
}
$id = qq("$id") if $id !~ /^".*"$/; $self->_imap_command("LOGIN $user $passwd")
$self->_imap_command("LOGIN $id $passwd")
or return undef; or return undef;
} }
@ -577,6 +572,7 @@ sub noop {
sub proxyauth { sub proxyauth {
my ( $self, $user ) = @_; my ( $self, $user ) = @_;
$user = ( $user eq "" ) ? qq("") : $self->Quote($user);
$self->_imap_command("PROXYAUTH $user") ? $self->Results : undef; $self->_imap_command("PROXYAUTH $user") ? $self->Results : undef;
} }
@ -741,33 +737,27 @@ sub subscribed {
return wantarray ? @folders : \@folders; return wantarray ? @folders : \@folders;
} }
# BUG? cleanup escaping/quoting
sub deleteacl { sub deleteacl {
my ( $self, $target, $user ) = @_; my ( $self, $target, $user ) = @_;
$target = $self->Massage($target); $target = $self->Massage($target);
$user =~ s/^"(.*)"$/$1/; $user = ( $user eq "" ) ? qq("") : $self->Quote($user);
$user =~ s/"/\\"/g;
$self->_imap_command(qq(DELETEACL $target "$user")) $self->_imap_command(qq(DELETEACL $target $user))
or return undef; or return undef;
return wantarray ? $self->History : $self->Results; return wantarray ? $self->History : $self->Results;
} }
# BUG? cleanup escaping/quoting
sub setacl { sub setacl {
my ( $self, $target, $user, $acl ) = @_; my ( $self, $target, $user, $acl ) = @_;
$target ||= $self->Folder; $target ||= $self->Folder;
$target = $self->Massage($target); $target = $self->Massage($target);
$user ||= $self->User; $user ||= $self->User;
$user =~ s/^"(.*)"$/$1/; $user = ( $user eq "" ) ? qq("") : $self->Quote($user);
$user =~ s/"/\\"/g; $acl = ( $acl eq "" ) ? qq("") : $self->Quote($acl);
$acl =~ s/^"(.*)"$/$1/; $self->_imap_command(qq(SETACL $target $user $acl))
$acl =~ s/"/\\"/g;
$self->_imap_command(qq(SETACL $target "$user" "$acl"))
or return undef; or return undef;
return wantarray ? $self->History : $self->Results; return wantarray ? $self->History : $self->Results;
@ -809,10 +799,9 @@ sub listrights {
$target = $self->Massage($target); $target = $self->Massage($target);
$user ||= $self->User; $user ||= $self->User;
$user =~ s/^"(.*)"$/$1/; $user = ( $user eq "" ) ? qq("") : $self->Quote($user);
$user =~ s/"/\\"/g;
$self->_imap_command(qq(LISTRIGHTS $target "$user")) $self->_imap_command(qq(LISTRIGHTS $target $user))
or return undef; or return undef;
my $resp = first { /^\* LISTRIGHTS/ } $self->History; my $resp = first { /^\* LISTRIGHTS/ } $self->History;
@ -2352,21 +2341,13 @@ sub uidexpunge {
return wantarray ? $self->History : $self->Results; return wantarray ? $self->History : $self->Results;
} }
# BUG? cleanup escaping/quoting
sub rename { sub rename {
my ( $self, $from, $to ) = @_; my ( $self, $from, $to ) = @_;
if ( $from =~ /^"(.*)"$/ ) { $from = ( $from eq "" ) ? qq("") : $self->Massage($from);
$from = $1 unless $self->exists($from); $to = ( $to eq "" ) ? qq("") : $self->Massage($to);
$from =~ s/"/\\"/g;
}
if ( $to =~ /^"(.*)"$/ ) { $self->_imap_command(qq(RENAME $from $to)) ? $self : undef;
$to = $1 unless $self->exists($from) && $from =~ /^".*"$/;
$to =~ s/"/\\"/g;
}
$self->_imap_command(qq(RENAME "$from" "$to")) ? $self : undef;
} }
sub status { sub status {
@ -3352,37 +3333,38 @@ sub getquotaroot {
return $self->_imap_command("GETQUOTAROOT $who") ? $self->Results : undef; return $self->_imap_command("GETQUOTAROOT $who") ? $self->Results : undef;
} }
# BUG? using user/$User here and INBOX in quota/quota_usage
sub getquota { sub getquota {
my ( $self, $what ) = @_; my ( $self, $what ) = @_;
my $who = $what ? $self->Massage($what) : "user/$self->{User}"; my $who = $what ? $self->Massage($what) : "user/" . $self->User;
return $self->_imap_command("GETQUOTA $who") ? $self->Results : undef; return $self->_imap_command("GETQUOTA $who") ? $self->Results : undef;
} }
# usage: $self->setquota($folder, storage => 512) # usage: $self->setquota($quotaroot, storage => 512, ...)
sub setquota(@) { sub setquota(@) {
my ( $self, $what ) = ( shift, shift ); my ( $self, $what ) = ( shift, shift );
my $who = $what ? $self->Massage($what) : "user/$self->{User}"; my $who = $what ? $self->Massage($what) : "user/" . $self->User;
my @limits; my @limits;
while (@_) { while (@_) {
my $key = uc shift @_; my ( $k, $v ) = ( $self->Quote( uc( shift @_ ) ), shift @_ );
push @limits, $key => shift @_; push( @limits, "($k $v)" );
} }
local $" = ' '; my $limits = join( ' ', @limits );
$self->_imap_command("SETQUOTA $who (@limits)") ? $self->Results : undef; $self->_imap_command("SETQUOTA $who $limits") ? $self->Results : undef;
} }
sub quota { sub quota {
my $self = shift; my ( $self, $what ) = ( shift, shift || "INBOX" );
my $what = shift || "INBOX"; my $tref = $self->getquota($what) or return undef;
$self->_imap_command("GETQUOTA $what") or $self->getquotaroot($what); shift @$tref; # pop off command
( map { /.*STORAGE\s+\d+\s+(\d+).*\n$/ ? $1 : () } $self->Results )[0]; return ( map { /.*STORAGE\s+\d+\s+(\d+).*\n$/ ? $1 : () } @$tref )[0];
} }
sub quota_usage { sub quota_usage {
my $self = shift; my ( $self, $what ) = ( shift, shift || "INBOX" );
my $what = shift || "INBOX"; my $tref = $self->getquota($what) or return undef;
$self->_imap_command("GETQUOTA $what") || $self->getquotaroot($what); shift @$tref; # pop off command
( map { /.*STORAGE\s+(\d+)\s+\d+.*\n$/ ? $1 : () } $self->Results )[0]; return ( map { /.*STORAGE\s+(\d+)\s+\d+.*\n$/ ? $1 : () } @$tref )[0];
} }
sub Quote($) { $_[0]->Massage( $_[1], NonFolderArg ) } sub Quote($) { $_[0]->Massage( $_[1], NonFolderArg ) }
@ -3395,15 +3377,16 @@ sub Quote($) { $_[0]->Massage( $_[1], NonFolderArg ) }
# resp-specials = "]" # resp-specials = "]"
# rfc2060: # rfc2060:
# CTL ::= <any ASCII control character and DEL, 0x00 - 0x1f, 0x7f> # CTL ::= <any ASCII control character and DEL, 0x00 - 0x1f, 0x7f>
# Additionally, we encode strings with } and [, be less than minimal # Paranoia/safety:
# encode strings with "}" / "[" / "]" / non-ascii chars
sub Massage($;$) { sub Massage($;$) {
my ( $self, $name, $notFolder ) = @_; my ( $self, $name, $notFolder ) = @_;
$name =~ s/^\"(.*)\"$/$1/ unless $notFolder; $name =~ s/^\"(.*)\"$/$1/s unless $notFolder;
if ( $name =~ /["\\]/ ) { if ( $name =~ /["\\[:^ascii:][:cntrl:]]/s ) {
return "{" . length($name) . "}" . $CRLF . $name; return "{" . length($name) . "}" . $CRLF . $name;
} }
elsif ( $name =~ /[(){}\s[:cntrl:]%*\[\]]/ ) { elsif ( $name =~ /[(){}\s%*\[\]]/s ) {
return qq("$name"); return qq("$name");
} }
else { else {

View file

@ -230,7 +230,7 @@ Example:
The B<Quote> method accepts a value as an argument and returns its The B<Quote> method accepts a value as an argument and returns its
argument as a correctly quoted string or a literal string. Since argument as a correctly quoted string or a literal string. Since
version 3.17 Mail::IMAPClient automatically quotes search arguments we version 3.17 Mail::IMAPClient automatically quotes search arguments we
use a SCALARREF so search will not modify or re-quite the valaue use a SCALARREF so search will not modify or re-quote the value
returned by B<Quote>. returned by B<Quote>.
Note this method should not be used on folder names for Note this method should not be used on folder names for
@ -783,6 +783,18 @@ The B<delete> method accepts a single argument, the name of a folder
to delete. It returns a true value on success and C<undef> on to delete. It returns a true value on success and C<undef> on
failure. failure.
=head2 deleteacl
Example:
$imap->deleteacl( $folder, $userid )
or die "Could not delete acl: $@\n";
The B<deleteacl> method accepts two input arguments, a folder name, a
user id (or authentication identifier, to use the terminology of
RFC2086). See RFC2086 for more information. (This is somewhat
experimental and its implementation may change.)
=head2 delete_message =head2 delete_message
Example: Example:
@ -945,7 +957,7 @@ server will likely respond with an error like I<* BAD Invalid tag>.
On failure <undef> is returned and L</LastError> is set. On failure <undef> is returned and L</LastError> is set.
See also L</idle>, L</imap_data> and L</Results>. See also L</idle>, L</idle_data> and L</Results>.
=head2 examine =head2 examine
@ -1277,10 +1289,15 @@ has been terminated by calling L</done>. Failure to do so will result
in an error and the idle command will typically be terminated by the in an error and the idle command will typically be terminated by the
server. server.
See also L</imap_data> and L</done>. See also L</idle_data> and L</done>.
=head2 idle_data =head2 idle_data
Usage:
# an optional timeout in seconds may be specified
$imap->idle_data( [$timeout] )
Example: Example:
my $tag = $imap->idle or warn "idle failed: $@\n"; my $tag = $imap->idle or warn "idle failed: $@\n";
@ -1292,12 +1309,12 @@ Example:
The B<idle_data> method can be used to accept any unsolicited mailbox The B<idle_data> method can be used to accept any unsolicited mailbox
update messages that have been sent by the server during an L</idle> update messages that have been sent by the server during an L</idle>
command. This method does not send any commands to the server, it command. This method does not send any commands to the server, it
simply waits for data from the server and returns that data to the simply looks for and optionally waits for data from the server and
caller. returns that data to the caller.
The B<idle> method accepts an optional $timeout argument and returns The B<idle_data> method accepts an optional $timeout argument and
an array (or an array reference if called in scalar context) with the returns an array (or an array reference if called in scalar context)
messages from the server. with the messages from the server.
By default a timeout of 0 seconds is used (do not block). Internally By default a timeout of 0 seconds is used (do not block). Internally
the timeout is passed to L<perlfunc/select>. The timeout controls how the timeout is passed to L<perlfunc/select>. The timeout controls how
@ -1399,6 +1416,87 @@ The B<get_header> method is a short-cut for:
my $messageId = $imap->parse_headers($msg,"Subject")->{"Subject"}[0]; my $messageId = $imap->parse_headers($msg,"Subject")->{"Subject"}[0];
=head2 getquotaroot
Example:
my $results = $imap->getquotaroot($mailboxname)
or die "Could not getquotaroot for $mailboxname: $@\n";
The B<getquotaroot> method implements the RFC2087 GETQUOTAROOT
command. The "$mailboxname" defaults to "INBOX" if no argument is
provided.
On error C<undef> is returned, otherwise L</Results> are returned.
The results should have the untagged QUOTAROOT response from the
server along with the QUOTAROOT's resource usage and limits in an
untagged QUOTA response.
See also B<RFC2087>, L</getquota>, L</setquota>, L</quota> and L</quota_usage>.
=head2 getquota
Example:
my $results = $imap->getquota($quotaroot)
or die "Could not getquota for $quotaroot: $@\n";
The B<getquota> method implements the RFC2087 GETQUOTA command. The
"$quotaroot" defaults to "user/I<User>" if no argument is provided.
On error C<undef> is returned, otherwise L</Results> are returned.
The results from the server should have the untagged QUOTA response
from the server.
See also B<RFC2087>, L</getquotaroot>, L</quota> and L</quota_usage>.
=head2 quota
Example:
my $limit = $imap->quota($quotaroot)
or die "Could not get quota limit for $quotaroot: $@\n";
The B<quota> method takes the L</Results> from L<getquota> and parses
out the "STORAGE" limit returned by the server. The "$quotaroot"
defaults to "INBOX" if no argument is provided.
On error C<undef> is returned, otherwise the integer "STORAGE" limit
provided by the server is returned.
See also B<RFC2087>, L</getquotaroot>, L</getquota> and L</quota_usage>.
=head2 quota_usage
Example:
my $usage = $imap->quota_usage($quotaroot)
or die "Could not get quota usage for $quotaroot: $@\n";
The B<quota_usage> method takes the L</Results> from L<getquota> and
parses out the "STORAGE" usage returned by the server. The
"$quotaroot" defaults to "INBOX" if no argument is provided.
On error C<undef> is returned, otherwise the integer "STORAGE" usage
provided by the server is returned.
See also B<RFC2087>, L</getquotaroot>, L</getquota> and L</quota>.
=head2 setquota
Example:
my $results = $imap->setquota( $quotaroot, $resource, $limit )
or die "Could not setquota for $quotaroot: $@\n";
The B<setquota> method implements the RFC2087 SETQUOTA command. It
accepts multiple pairs of $resource and $limit arguments. The
"$quotaroot" defaults to "user/I<User>" if not defined.
On error C<undef> is returned, otherwise L</Results> are returned.
See also B<RFC2087>, L</getquotaroot> and L</getquota>.
=head2 is_parent =head2 is_parent
Example: Example:
@ -1477,7 +1575,8 @@ and $@ is set. The methods L</new>, L</connect>, and L</Socket> may
automatically invoke B<login> see the documentation of each method for automatically invoke B<login> see the documentation of each method for
details. details.
If the L</Compress> parameter is set, the L</compress> method will automatically be called after successful authentication. If the L</Compress> parameter is set, the L</compress> method will
automatically be called after successful authentication.
See also L</proxyauth> and L</Proxy> for additional information See also L</proxyauth> and L</Proxy> for additional information
regarding ways of authenticating with a server via SASL and/or regarding ways of authenticating with a server via SASL and/or
@ -2298,7 +2397,7 @@ which is why you don't have to worry about it overly much.)
Example: Example:
$imap->setacl($folder,$userid,$authstring) $imap->setacl( $folder, $userid, $aclstring )
or die "Could not set acl: $@\n"; or die "Could not set acl: $@\n";
The B<setacl> method accepts three input arguments, a folder name, a The B<setacl> method accepts three input arguments, a folder name, a
@ -3771,7 +3870,7 @@ http://rt.cpan.org/Public/Dist/Display.html?Name=Mail-IMAPClient
Copyright (C) 1999-2003 The Kernen Group, Inc. Copyright (C) 1999-2003 The Kernen Group, Inc.
Copyright (C) 2007-2009 Mark Overmeer Copyright (C) 2007-2009 Mark Overmeer
Copyright (C) 2010-2011 Phil Pearl (Lobbes) Copyright (C) 2010-2012 Phil Pearl (Lobbes)
All rights reserved. All rights reserved.
This library is free software; you can redistribute it and/or modify This library is free software; you can redistribute it and/or modify

View file

@ -12,8 +12,8 @@ my $parser = Mail::IMAPClient::BodyStructure::Parse->new
or die "Cannot parse rules: $@\n" or die "Cannot parse rules: $@\n"
. "Try remaking Mail::IMAPClient::BodyStructure::Parse.\n"; . "Try remaking Mail::IMAPClient::BodyStructure::Parse.\n";
sub new sub new {
{ my $class = shift; my $class = shift;
my $bodystructure = shift; my $bodystructure = shift;
my $self = $parser->start($bodystructure) my $self = $parser->start($bodystructure)
@ -26,19 +26,21 @@ sub new
bless $self, ref($class) || $class; bless $self, ref($class) || $class;
} }
sub _get_thingy sub _get_thingy {
{ my $thingy = shift; my $thingy = shift;
my $object = shift || ( ref $thingy ? $thingy : undef ); my $object = shift || ( ref $thingy ? $thingy : undef );
unless ($object && ref $object) unless ( $object && ref $object ) {
{ warn $@ = "No argument passed to $thingy method."; warn $@ = "No argument passed to $thingy method.";
return undef; return undef;
} }
unless(UNIVERSAL::isa($object, 'HASH') && exists $object->{$thingy}) unless ( UNIVERSAL::isa( $object, 'HASH' ) && exists $object->{$thingy} ) {
{ my $a = $thingy =~ /^[aeiou]/i ? 'an' : 'a'; my $a = $thingy =~ /^[aeiou]/i ? 'an' : 'a';
my $has = ref $object eq 'HASH' ? join( ", ", keys %$object ) : ''; my $has = ref $object eq 'HASH' ? join( ", ", keys %$object ) : '';
warn $@ = ref($object)." $object does not have $a $thingy. " warn $@ =
ref($object)
. " $object does not have $a $thingy. "
. ( $has ? "It has $has" : '' ); . ( $has ? "It has $has" : '' );
return undef; return undef;
} }
@ -49,17 +51,19 @@ sub _get_thingy
$value; $value;
} }
BEGIN BEGIN {
{ no strict 'refs'; no strict 'refs';
foreach my $datum ( foreach my $datum (
qw/ bodytype bodysubtype bodyparms bodydisp bodyid bodydesc bodyenc qw/ bodytype bodysubtype bodyparms bodydisp bodyid bodydesc bodyenc
bodysize bodylang envelopestruct textlines / ) bodysize bodylang envelopestruct textlines /
{ *$datum = sub { _get_thingy($datum, @_) }; )
{
*$datum = sub { _get_thingy( $datum, @_ ) };
} }
} }
sub parts sub parts {
{ my $self = shift; my $self = shift;
return wantarray ? @{ $self->{PartsList} } : $self->{PartsList} return wantarray ? @{ $self->{PartsList} } : $self->{PartsList}
if exists $self->{PartsList}; if exists $self->{PartsList};
@ -67,14 +71,14 @@ sub parts
$self->{PartsList} = \@parts; $self->{PartsList} = \@parts;
# BUG?: should this default to ($HEAD, TEXT) # BUG?: should this default to ($HEAD, TEXT)
unless(exists $self->{bodystructure}) unless ( exists $self->{bodystructure} ) {
{ $self->{PartsIndex}{1} = $self; $self->{PartsIndex}{1} = $self;
@parts = ( $HEAD, 1 ); @parts = ( $HEAD, 1 );
return wantarray ? @parts : \@parts; return wantarray ? @parts : \@parts;
} }
foreach my $p ($self->bodystructure) foreach my $p ( $self->bodystructure ) {
{ my $id = $p->id; my $id = $p->id;
push @parts, $id; push @parts, $id;
$self->{PartsIndex}{$id} = $p; $self->{PartsIndex}{$id} = $p;
my $type = uc $p->bodytype || ''; my $type = uc $p->bodytype || '';
@ -86,17 +90,17 @@ sub parts
wantarray ? @parts : \@parts; wantarray ? @parts : \@parts;
} }
sub bodystructure sub bodystructure {
{ my $self = shift; my $self = shift;
my $partno = 0; my $partno = 0;
my @parts; my @parts;
if($self->{_top}) if ( $self->{_top} ) {
{ $self->{_id} ||= $HEAD; $self->{_id} ||= $HEAD;
$self->{_prefix} ||= $HEAD; $self->{_prefix} ||= $HEAD;
$partno = 0; $partno = 0;
foreach my $b ( @{$self->{bodystructure}} ) foreach my $b ( @{ $self->{bodystructure} } ) {
{ $b->{_id} = ++$partno; $b->{_id} = ++$partno;
$b->{_prefix} = $partno; $b->{_prefix} = $partno;
push @parts, $b, $b->bodystructure; push @parts, $b, $b->bodystructure;
} }
@ -106,8 +110,8 @@ sub bodystructure
my $prefix = $self->{_prefix} || ""; my $prefix = $self->{_prefix} || "";
$prefix =~ s/\.?$/./; $prefix =~ s/\.?$/./;
foreach my $p ( @{$self->{bodystructure}} ) foreach my $p ( @{ $self->{bodystructure} } ) {
{ $partno++; $partno++;
# BUG?: old code didn't add .TEXT sections, should we skip these? # BUG?: old code didn't add .TEXT sections, should we skip these?
# - This code needs to be generalised (maybe it belongs in parts()?) # - This code needs to be generalised (maybe it belongs in parts()?)
@ -134,8 +138,8 @@ sub bodystructure
wantarray ? @parts : \@parts; wantarray ? @parts : \@parts;
} }
sub id sub id {
{ my $self = shift; my $self = shift;
return $self->{_id} return $self->{_id}
if exists $self->{_id}; if exists $self->{_id};
@ -143,13 +147,13 @@ sub id
if $self->{_top}; if $self->{_top};
# BUG?: can this be removed? ... seems wrong # BUG?: can this be removed? ... seems wrong
if ($self->{bodytype} eq 'MULTIPART') if ( $self->{bodytype} eq 'MULTIPART' ) {
{ my $p = $self->{_id} || $self->{_prefix}; my $p = $self->{_id} || $self->{_prefix};
$p =~ s/\.$//; $p =~ s/\.$//;
return $p; return $p;
} }
else else {
{ return $self->{_id} ||= 1; return $self->{_id} ||= 1;
} }
} }
@ -159,13 +163,13 @@ our @ISA = qw/Mail::IMAPClient::BodyStructure/;
package Mail::IMAPClient::BodyStructure::Envelope; package Mail::IMAPClient::BodyStructure::Envelope;
our @ISA = qw/Mail::IMAPClient::BodyStructure/; our @ISA = qw/Mail::IMAPClient::BodyStructure/;
sub new sub new {
{ my ($class, $envelope) = @_; my ( $class, $envelope ) = @_;
$parser->envelope($envelope); $parser->envelope($envelope);
} }
sub parse_string sub parse_string {
{ my ($class, $envelope) = @_; my ( $class, $envelope ) = @_;
$envelope = "(" . $envelope . ")" unless ( $envelope =~ /^\(/ ); $envelope = "(" . $envelope . ")" unless ( $envelope =~ /^\(/ );
$parser->envelopestruct($envelope); $parser->envelopestruct($envelope);
} }
@ -177,14 +181,14 @@ sub to_addresses { shift->_addresses(to => 0) }
sub cc_addresses { shift->_addresses( cc => 0 ) } sub cc_addresses { shift->_addresses( cc => 0 ) }
sub bcc_addresses { shift->_addresses( bcc => 0 ) } sub bcc_addresses { shift->_addresses( bcc => 0 ) }
sub _addresses($$$) sub _addresses($$$) {
{ my ($self, $name, $isSender) = @_; my ( $self, $name, $isSender ) = @_;
ref $self->{$name} eq 'ARRAY' ref $self->{$name} eq 'ARRAY'
or return (); or return ();
my @list; my @list;
foreach ( @{$self->{$name}} ) foreach ( @{ $self->{$name} } ) {
{ my $pn = $_->personalname; my $pn = $_->personalname;
my $name = $pn && $pn ne 'NIL' ? "$pn " : ''; my $name = $pn && $pn ne 'NIL' ? "$pn " : '';
push @list, $name . '<' . $_->mailboxname . '@' . $_->hostname . '>'; push @list, $name . '<' . $_->mailboxname . '@' . $_->hostname . '>';
} }
@ -194,20 +198,22 @@ sub _addresses($$$)
: \@list; : \@list;
} }
BEGIN BEGIN {
{ no strict 'refs'; no strict 'refs';
for my $datum ( qw(subject inreplyto from messageid bcc date for my $datum (
replyto to sender cc)) qw(subject inreplyto from messageid bcc date
{ *$datum = sub { @_ > 1 ? $_[0]->{$datum} = $_[1] : $_[0]->{$datum} } replyto to sender cc)
)
{
*$datum = sub { @_ > 1 ? $_[0]->{$datum} = $_[1] : $_[0]->{$datum} }
} }
} }
package Mail::IMAPClient::BodyStructure::Address; package Mail::IMAPClient::BodyStructure::Address;
our @ISA = qw/Mail::IMAPClient::BodyStructure/; our @ISA = qw/Mail::IMAPClient::BodyStructure/;
for my $datum ( qw(personalname mailboxname hostname sourcename) ) for my $datum (qw(personalname mailboxname hostname sourcename)) {
{ no strict 'refs'; no strict 'refs';
*$datum = sub { shift->{$datum}; }; *$datum = sub { shift->{$datum}; };
} }
@ -221,38 +227,32 @@ Mail::IMAPClient::BodyStructure - parse fetched results
=head1 SYNOPSIS =head1 SYNOPSIS
use Mail::IMAPClient::BodyStructure;
use Mail::IMAPClient; use Mail::IMAPClient;
use Mail::IMAPClient::BodyStructure;
my $imap = Mail::IMAPClient->new(Server=>$serv,User=>$usr,Password=>$pwd); my $imap = Mail::IMAPClient->new(
$imap->select("INBOX") or die "cannot select the inbox for $usr: $@\n"; Server => $server, User => $login, Password => $pass
);
my @recent = $imap->search("recent"); $imap->select("INBOX") or die "Could not select INBOX: $@\n";
foreach my $id (@recent) my @recent = $imap->search("recent") or die "No recent msgs in INBOX\n";
{ my $fetched = $imap->fetch($id, "bodystructure");
my $struct = Mail::IMAPClient::BodyStructure->new($fetched);
my $mime = $struct->bodytype."/".$struct->bodysubtype; foreach my $id (@recent) {
my $parts =join "\n\t", $struct->parts; my $bsdat = $imap->fetch( $id, "bodystructure" );
print "Msg $id (Content-type: $mime) contains these parts:\n\t$parts\n"; my $bso = Mail::IMAPClient::BodyStructure->new($bsdat);
my $mime = $bso->bodytype . "/" . $bso->bodysubtype;
my $parts = map( "\n\t" . $_, $bso->parts );
print "Msg $id (Content-type: $mime) contains these parts:$parts\n";
} }
=head1 DESCRIPTION =head1 DESCRIPTION
This extension will parse the result of an IMAP FETCH BODYSTRUCTURE This extension will parse the result of an IMAP FETCH BODYSTRUCTURE
command into a perl data structure. It also provides helper methods that command into a perl data structure. It also provides helper methods
will help you pull information out of the data structure. to help pull information out of the data structure.
Use of this extension requires Parse::RecDescent. If you don't have This module requires Parse::RecDescent.
Parse::RecDescent then you must either get it or refrain from using
this module.
=head2 EXPORT
Nothing is exported by default. C<$parser> is exported upon
request. C<$parser> is the BodyStucture object's Parse::RecDescent object,
which you'll probably only need for debugging purposes.
=head1 Class Methods =head1 Class Methods
@ -261,21 +261,13 @@ The following class method is available:
=head2 new =head2 new
This class method is the constructor method for instantiating new This class method is the constructor method for instantiating new
Mail::IMAPClient::BodyStructure objects. The B<new> method accepts one Mail::IMAPClient::BodyStructure objects. The B<new> method accepts
argument, a string containing a server response to a FETCH BODYSTRUCTURE one argument, a string containing a server response to a FETCH
directive. Only one message's body structure should be described in this BODYSTRUCTURE directive.
string, although that message may contain an arbitrary number of parts.
If you know the messages sequence number or unique ID (UID) The module B<Mail::IMAPClient> provides the B<get_bodystructure>
but haven't got its body structure, and you want to get the body conveniece method to simplify use of this module when starting with
structure and parse it into a B<Mail::IMAPClient::BodyStructure> just a messages sequence number or unique ID (UID).
object, then you might as well save yourself some work and use
B<Mail::IMAPClient>'s B<get_bodystructure> method, which accepts
a message sequence number (or UID if I<Uid> is true) and returns a
B<Mail::IMAPClient::BodyStructure> object. It's functionally equivalent
to issuing the FETCH BODYSTRUCTURE IMAP client command and then passing
the results to B<Mail::IMAPClient::BodyStructure>'s B<new> method but
it does those things in one simple method call.
=head1 Object Methods =head1 Object Methods
@ -344,10 +336,8 @@ calling B<Mail::IMAPClient::Bodystructure> object.
=head2 envelopestruct =head2 envelopestruct
The B<envelopestruct> object method requires no arguments. It returns The B<envelopestruct> object method requires no arguments. It returns
the envelopestruct for the message whose structure is described by the a B<Mail::IMAPClient::BodyStructure::Envelope> object for the message
calling B<Mail::IMAPClient::Bodystructure> object. This envelope structure from the calling B<Mail::IMAPClient::Bodystructure> object.
is blessed into the B<Mail::IMAPClient::BodyStructure::Envelope> subclass,
which is explained more fully below.
=head2 textlines =head2 textlines
@ -355,7 +345,7 @@ The B<textlines> object method requires no arguments. It returns the
textlines for the message whose structure is described by the calling textlines for the message whose structure is described by the calling
B<Mail::IMAPClient::Bodystructure> object. B<Mail::IMAPClient::Bodystructure> object.
=head1 Envelopes and the Mail::IMAPClient::BodyStructure::Envelope Subclass =head1 Mail::IMAPClient::BodyStructure::Envelope
The IMAP standard specifies that output from the IMAP B<FETCH The IMAP standard specifies that output from the IMAP B<FETCH
ENVELOPE> command will be an RFC2060 envelope structure. It further ENVELOPE> command will be an RFC2060 envelope structure. It further
@ -367,10 +357,11 @@ of these envelope structures, which is to say the nested parenthetical
lists of RFC2060 translated into a Perl datastructure. lists of RFC2060 translated into a Perl datastructure.
Note that all of the fields relate to the specific part to which they Note that all of the fields relate to the specific part to which they
belong. In other words, output from a FETCH nnnn ENVELOPE command (or, belong. In other words, output from a FETCH nnnn ENVELOPE command
in B<Mail::IMAPClient>, C<$imap->fetch($msgid,"ENVELOPE")> or C<my $env = (or, in B<Mail::IMAPClient>, C<$imap->fetch($msgid,"ENVELOPE")> or
$imap->get_envelope($msgid)>) are for the message, but fields from within C<my $env = $imap->get_envelope($msgid)>) are for the message, but
a bodystructure relate to the message subpart and not the parent message. fields from within a bodystructure relate to the message subpart and
not the parent message.
An envelope structure's B<Mail::IMAPClient::BodyStructure::Envelope> An envelope structure's B<Mail::IMAPClient::BodyStructure::Envelope>
representation is a hash of thingies that looks like this: representation is a hash of thingies that looks like this:
@ -411,17 +402,17 @@ Returns the message id of the message.
=back =back
You can also use the following methods to get addressing You can also use the following methods to get addressing information.
information. Each of these methods returns an array of Each of these methods returns an array of
B<Mail::IMAPClient::BodyStructure::Address> objects, which are perl B<Mail::IMAPClient::BodyStructure::Address> objects, which are perl
data structures representing RFC2060 address structures. Some of these data structures representing RFC2060 address structures. Some of
arrays would naturally contain one element (such as B<from>, which these arrays would naturally contain one element (such as B<from>,
normally contains a single "From:" address); others will often contain which normally contains a single "From:" address); others will often
more than one address. However, because RFC2060 defines all of these as contain more than one address. However, because RFC2060 defines all
"lists of address structures", they are all translated into arrays of of these as "lists of address structures", they are all translated
B<...::Address> objects. into arrays of B<...::Address> objects.
See the section on B<Mail::IMAPClient::BodyStructure::Address>", below, See the section on B<Mail::IMAPClient::BodyStructure::Address>, below,
for alternate (and preferred) ways of accessing these data. for alternate (and preferred) ways of accessing these data.
The methods available are: The methods available are:
@ -430,9 +421,9 @@ The methods available are:
=item bcc =item bcc
Returns an array of blind cc'ed recipients' address structures. (Don't Returns an array of blind cc'ed recipients' address structures.
expect much in here unless the message was sent from the mailbox you're (Don't expect much in here unless the message was sent from the
poking around in, by the way.) mailbox you're poking around in, by the way.)
=item cc =item cc
@ -444,8 +435,8 @@ Returns an array of "From:" address structures--usually just one.
=item replyto =item replyto
Returns an array of "Reply-to:" address structures. Once again there is Returns an array of "Reply-to:" address structures. Once again there
usually just one address in the list. is usually just one address in the list.
=item sender =item sender
@ -459,12 +450,12 @@ Returns an array of recipients' address structures.
=back =back
Each of the methods that returns a list of address structures (i.e. a Each of the methods that returns a list of address structures (i.e. a
list of B<Mail::IMAPClient::BodyStructure::Address> arrays) also has an list of B<Mail::IMAPClient::BodyStructure::Address> arrays) also has
analagous method that will return a list of E-Mail addresses instead. The an analagous method that will return a list of E-Mail addresses
addresses are in the format C<personalname E<lt>mailboxname@hostnameE<gt>> instead. The addresses are in the format C<personalname
(see the section on B<Mail::IMAPClient::BodyStructure::Address>, E<lt>mailboxname@hostnameE<gt>> (see the section on
below) However, if the personal name is 'NIL' then it is omitted from B<Mail::IMAPClient::BodyStructure::Address>, below) However, if the
the address. personal name is 'NIL' then it is omitted from the address.
These methods are: These methods are:
@ -472,65 +463,66 @@ These methods are:
=item bcc_addresses =item bcc_addresses
Returns a list (or an array reference if called in scalar context) Returns a list (or an array reference if called in scalar context) of
of blind cc'ed recipients' email addresses. (Don't expect much in here blind cc'ed recipients' email addresses. (Don't expect much in here
unless the message was sent from the mailbox you're poking around in, unless the message was sent from the mailbox you're poking around in,
by the way.) by the way.)
=item cc_addresses =item cc_addresses
Returns a list of cc'ed recipients' email addresses. If called in a scalar Returns a list of cc'ed recipients' email addresses. If called in a
context it returns a reference to an array of email addresses. scalar context it returns a reference to an array of email addresses.
=item from_addresses =item from_addresses
Returns a list of "From:" email addresses. If called in a scalar context Returns a list of "From:" email addresses. If called in a scalar
it returns the first email address in the list. (It's usually a list of just context it returns the first email address in the list. (It's usually
one anyway.) a list of just one anyway.)
=item replyto_addresses =item replyto_addresses
Returns a list of "Reply-to:" email addresses. If called in a scalar context Returns a list of "Reply-to:" email addresses. If called in a scalar
it returns the first email address in the list. context it returns the first email address in the list.
=item sender_addresses =item sender_addresses
Returns a list of senders' email addresses. If called in a scalar context Returns a list of senders' email addresses. If called in a scalar
it returns the first email address in the list. context it returns the first email address in the list.
=item to_addresses =item to_addresses
Returns a list of recipients' email addresses. If called in a scalar context Returns a list of recipients' email addresses. If called in a scalar
it returns a reference to an array of email addresses. context it returns a reference to an array of email addresses.
=back =back
Note that context affects the behavior of all of the above methods. Note that context affects the behavior of all of the above methods.
Those fields that will commonly contain multiple entries (i.e. they are Those fields that will commonly contain multiple entries (i.e. they
recipients) will return an array reference when called in scalar context. are recipients) will return an array reference when called in scalar
You can use this behavior to optimize performance. context. You can use this behavior to optimize performance.
Those fields that will commonly contain just one address (the sender's) will Those fields that will commonly contain just one address (the
return the first (and usually only) address. You can use this behavior to sender's) will return the first (and usually only) address. You can
optimize your development time. use this behavior to optimize your development time.
=head1 Addresses and the Mail::IMAPClient::BodyStructure::Address =head1 Addresses and the Mail::IMAPClient::BodyStructure::Address
Several components of an envelope structure are address Several components of an envelope structure are address structures.
structures. They are each parsed into their own object, They are each parsed into their own object,
B<Mail::IMAPClient::BodyStructure::Address>, which looks like this: B<Mail::IMAPClient::BodyStructure::Address>, which looks like this:
{ mailboxname => 'somebody.special' {
, hostname => 'somplace.weird.com' mailboxname => 'somebody.special',
, personalname => 'Somebody Special hostname => 'somplace.weird.com'
, sourceroute => 'NIL' personalname => 'Somebody Special
sourceroute => 'NIL'
} }
RFC2060 specifies that each address component of a bodystructure is a RFC2060 specifies that each address component of a bodystructure is a
list of address structures, so B<Mail::IMAPClient::BodyStructure> parses list of address structures, so B<Mail::IMAPClient::BodyStructure>
each of these into an array of B<Mail::IMAPClient::BodyStructure::Address> parses each of these into an array of
objects. B<Mail::IMAPClient::BodyStructure::Address> objects.
Each of these objects has the following methods available to it: Each of these objects has the following methods available to it:
@ -543,13 +535,13 @@ the left of the '@' sign.
=item hostname =item hostname
Returns the "hostname" portion of the address, which is the part to the Returns the "hostname" portion of the address, which is the part to
right of the '@' sign. the right of the '@' sign.
=item personalname =item personalname
Returns the "personalname" portion of the address, which is the part of Returns the "personalname" portion of the address, which is the part
the address that's treated like a comment. of the address that's treated like a comment.
=item sourceroute =item sourceroute
@ -557,8 +549,8 @@ Returns the "sourceroute" portion of the address, which is typically "NIL".
=back =back
Taken together, the parts of an address structure form an address that will Taken together, the parts of an address structure form an address that
look something like this: will look something like this:
C<personalname E<lt>mailboxname@hostnameE<gt>> C<personalname E<lt>mailboxname@hostnameE<gt>>
@ -566,21 +558,19 @@ Note that because the B<Mail::IMAPClient::BodyStructure::Address>
objects come in arrays, it's generally easier to use the methods objects come in arrays, it's generally easier to use the methods
available to B<Mail::IMAPClient::BodyStructure::Envelope> to obtain available to B<Mail::IMAPClient::BodyStructure::Envelope> to obtain
all of the addresses in a particular array in one operation. These all of the addresses in a particular array in one operation. These
methods are provided, however, in case you'd rather do things methods are provided, however, in case you'd rather do things the hard
the hard way. (And also because the aforementioned methods from way. (And also because the aforementioned methods from
B<Mail::IMAPClient::BodyStructure::Envelope> need them anyway.) B<Mail::IMAPClient::BodyStructure::Envelope> need them anyway.)
=cut =cut
=head1 AUTHOR =head1 AUTHOR
David J. Kernen Original author: David J. Kernen; Reworked by: Mark Overmeer;
Maintained by Phil Pearl.
Reworked and maintained by Mark Overmeer.
=head1 SEE ALSO =head1 SEE ALSO
perl(1), Mail::IMAPClient, and RFC2060. See also Parse::RecDescent if you perl(1), Mail::IMAPClient, Parse::RecDescent, and RFC2060.
want to understand the internals of this module.
=cut =cut

View file

@ -413,11 +413,14 @@ ok( $imap->reconnect, "reconnect" );
ok_relaxed_logout($imap); ok_relaxed_logout($imap);
# Test STARTTLS - an optional feature so tests always succeed # STARTTLS - an optional feature
{ if ( $imap->_load_module("SSL") ) {
$imap->connect( Starttls => 1 ); $imap->connect( Ssl => 0, Starttls => 1 );
ok( 1, "OPTIONAL connect(Starttls=>1)" . ( $@ ? ": (error) $@ " : "" ) ); ok( 1, "OPTIONAL connect(Starttls=>1)" . ( $@ ? ": (error) $@ " : "" ) );
} }
else {
ok( 1, "skipping optional STARTTLS test" );
}
# LOGOUT # LOGOUT
# - on successful LOGOUT $code is OK (not BYE!) see RFC 3501 sect 7.1.5 # - on successful LOGOUT $code is OK (not BYE!) see RFC 3501 sect 7.1.5

30
W/learn/data_utf7 Normal file
View file

@ -0,0 +1,30 @@
[&ZTZO9nux-]
[&ZTZO9nux-/263&cO1+vw-]
[&ZTZO9nux-/&kK57sZXumJg-]
[&ZTZO9nux-/&fwFb+G3u-]
[&ZTZO9nux-/11111]
[&XfJT0ZAB-]
[&XfJT0ZAB-/321]
[&XfJSIJZk-]
[&XfJSIJZk-/&fwFb+G3u-]
[&g0l6Pw-]
[&Tg1mDpCuTvZZOQ-]
[&XfJfUmhj-]
[&XfJfUmhj-/&VGhfi14I-]
[&XfJfUmhj-/&Ti1W,U4Hf1E-]
[&XfJfUmhj-/&f1F62Q-]
[&XfJfUmhj-/&UWh0Aw-]
[&XfJfUmhj-/&UWh0Aw-/11]
[&XfJfUmhj-/&fwFb+G3u-]
[&XfJfUmhj-/&X66Pbw-eip]
[&XfJfUmhj-/China Tax Service]
[&XfJfUmhj-/IT&ZXR0Bg-]
[&XfJfUmhj-/&cGuPZnlo-]
[&XfJfUmhj-/&UWhl9g-]
[&XfJfUmhj-/&dTWL3U8ai64-]
[&XfJfUmhj-/&V,mLrQ-]
[&XfJfUmhj-/&cO1wuU,hYG+QH5AS-]
[Sent Messages]
[Deleted Messages]
[&V4NXPpCuTvY-]
[&XfJSIJZkkK5O9g-]

13
W/learn/imap_utf7 Executable file
View file

@ -0,0 +1,13 @@
#!/usr/bin/perl
use Unicode::IMAPUtf7;
my $t = Unicode::IMAPUtf7->new();
while (<>) {
chomp ;
push( @result, sprintf( "%33s %s\n", $_, $t->decode($_) ) ) ;
}
print @result ;

41
W/ml_announce.in Normal file
View file

@ -0,0 +1,41 @@
m4_dnl $Id: ml_announce.in,v 1.3 2012/09/11 21:01:53 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
m4_dnl
From: Gilles LAMIRAL <gilles.lamiral@laposte.net>
Bcc: gilles@lamiral.info
Subject: [imapsync update] new imapsync release M4_imapsync_VERSION available
To: imapsync_update@lists.lamiral.info
Hello imapsync user,
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.
You will find the latest imapsync.exe binary (release M4_imapsync_VERSION)
and the latest imapsync source code (release M4_imapsync_VERSION) at the following link:
http://imapsync.lamiral.info/dist/M4_SECRET_PATH/
Three files are there:
- imapsync is directly the perl script (also found in the tarball) for a fast upgrade.
- imapsync-M4_imapsync_VERSION.tgz is the tarball containing everything of the project (maybe too much)
- imapsync.exe is the win32 standalone binary.
What's new in this M4_imapsync_VERSION release can be found at
http://imapsync.lamiral.info/#latest
I thank you again for buying and using imapsync,
I wish you successful imap transfers!
Feedback is welcome!
Web site: http://imapsync.lamiral.info/
--
Au revoir.
Gilles Lamiral, La Billais, 35580 Baulon, France
tel +33 951 84 42 42
mob +33 620 79 76 06

View file

@ -1,13 +1,13 @@
#!/bin/sh #!/bin/sh
# $Id: paypal_run_dev,v 1.5 2011/05/20 10:50:05 gilles Exp gilles $ # $Id: paypal_run_dev,v 1.7 2012/09/10 11:53:37 gilles Exp gilles $
set -e set -e
#set -x #set -x
# Add path to commands at home # Add path to commands at home
PATH=$PATH:/g/public_html/imapsync/W/paypal_reply PATH=$PATH:/g/public_html/imapsync/W/paypal_reply
PERL5LIB=/g/public_html/imapsync/Mail-IMAPClient-3.30/lib PERL5LIB=/g/public_html/imapsync/Mail-IMAPClient-3.32/lib
export PERL5LIB export PERL5LIB
test -f /g/public_html/imapsync/W/paypal_reply/paypal_functions \ test -f /g/public_html/imapsync/W/paypal_reply/paypal_functions \

View file

@ -1,6 +1,6 @@
#!/bin/sh #!/bin/sh
# $Id: paypal_run_laposte,v 1.5 2012/08/24 14:18:02 gilles Exp gilles $ # $Id: paypal_run_laposte,v 1.6 2012/09/10 11:54:33 gilles Exp gilles $
set -e set -e
#set -x #set -x
@ -8,7 +8,7 @@ set -e
# Add path to commands at home # Add path to commands at home
PATH=$PATH:/g/public_html/imapsync/W/paypal_reply PATH=$PATH:/g/public_html/imapsync/W/paypal_reply
PERL5LIB=/g/public_html/imapsync/Mail-IMAPClient-3.30/lib PERL5LIB=/g/public_html/imapsync/Mail-IMAPClient-3.32/lib
export PERL5LIB export PERL5LIB
test -f /g/public_html/imapsync/W/paypal_reply/paypal_functions \ test -f /g/public_html/imapsync/W/paypal_reply/paypal_functions \

View file

@ -1,2 +1,6 @@
imapsync \ --host1 p --user1 toto --passfile1 secret.toto \ --host2 p --user2 titi --passfile2 secret.titi REM
imapsync \ --host1 p --user1 tata --passfile1 secret.tata \ --host2 p --user2 titi --passfile2 secret.titi
cd C:\msys\1.0\home\Admin\imapsync
REM imapsync.exe \ --host1 p --user1 toto --passfile1 secret.toto \ --host2 p --user2 titi --passfile2 secret.titi
.\imapsync.exe \ --host1 p --user1 tata --passfile1 secret.tata \ --host2 p --user2 titi --passfile2 secret.titi

4
i3
View file

@ -1,7 +1,7 @@
#!/bin/sh #!/bin/sh
# $Id: i3,v 1.10 2012/08/12 23:15:15 gilles Exp gilles $ # $Id: i3,v 1.11 2012/09/11 21:00:06 gilles Exp gilles $
BASE=`dirname $0` BASE=`dirname $0`
perl -I${BASE}/W/Mail-IMAPClient-3.31/lib ${BASE}/imapsync "$@" perl -I${BASE}/W/Mail-IMAPClient-3.32/lib ${BASE}/imapsync "$@"

127
imapsync
View file

@ -20,7 +20,7 @@ Synchronise mailboxes between two imap servers.
Good at IMAP migration. More than 44 different IMAP server softwares Good at IMAP migration. More than 44 different IMAP server softwares
supported with success. supported with success.
$Revision: 1.504 $ $Revision: 1.508 $
=head1 SYNOPSIS =head1 SYNOPSIS
@ -515,7 +515,7 @@ Entries for imapsync:
Feedback (good or bad) will often be welcome. Feedback (good or bad) will often be welcome.
$Id: imapsync,v 1.504 2012/08/28 13:10:26 gilles Exp gilles $ $Id: imapsync,v 1.508 2012/09/10 21:10:13 gilles Exp gilles $
=cut =cut
@ -589,6 +589,7 @@ my(
$version, $help, $version, $help,
$justconnect, $justfolders, $justbanner, $justconnect, $justfolders, $justbanner,
$fast, $fast,
$total_bytes_transferred, $total_bytes_transferred,
$total_bytes_skipped, $total_bytes_skipped,
$total_bytes_error, $total_bytes_error,
@ -603,6 +604,12 @@ my(
$h2_total_bytes_duplicate, $h2_total_bytes_duplicate,
$h1_nb_msg_deleted, $h1_nb_msg_deleted,
$h2_nb_msg_deleted, $h2_nb_msg_deleted,
$h1_bytes_processed,
$h1_nb_msg_processed,
$h1_nb_msg_start, $h1_bytes_start,
$h2_nb_msg_start, $h2_bytes_start,
$timeout, $timeout,
$timestart, $timestart_int, $timeend, $timediff, $timestart, $timestart_int, $timeend, $timediff,
$timesize, $timebefore, $timesize, $timebefore,
@ -627,13 +634,14 @@ my(
$addheader, $addheader,
%h1, %h2, %h1, %h2,
$checkselectable, $checkmessageexists, $checkselectable, $checkmessageexists,
$expungeaftereach,
); );
# main program # main program
# global variables initialisation # global variables initialisation
$rcs = '$Id: imapsync,v 1.504 2012/08/28 13:10:26 gilles Exp gilles $ '; $rcs = '$Id: imapsync,v 1.508 2012/09/10 21:10:13 gilles Exp gilles $ ';
$total_bytes_transferred = 0; $total_bytes_transferred = 0;
$total_bytes_skipped = 0; $total_bytes_skipped = 0;
@ -645,6 +653,11 @@ $h1_nb_msg_duplicate = $h2_nb_msg_duplicate = 0;
$h1_nb_msg_noheader = $h2_nb_msg_noheader = 0; $h1_nb_msg_noheader = $h2_nb_msg_noheader = 0;
$h1_total_bytes_duplicate = $h2_total_bytes_duplicate = 0; $h1_total_bytes_duplicate = $h2_total_bytes_duplicate = 0;
$h1_nb_msg_start = $h1_bytes_start = 0 ;
$h2_nb_msg_start = $h2_bytes_start = 0 ;
$h1_nb_msg_processed = $h1_bytes_processed = 0 ;
$nb_errors = 0; $nb_errors = 0;
$max_msg_size_in_bytes = 0; $max_msg_size_in_bytes = 0;
@ -715,6 +728,7 @@ $cacheaftercopy = 1 if ( $usecache and ( ! defined( $cacheaftercopy ) ) ) ;
$checkselectable = defined( $checkselectable ) ? $checkselectable : 1 ; $checkselectable = defined( $checkselectable ) ? $checkselectable : 1 ;
$checkmessageexists = defined( $checkmessageexists ) ? $checkmessageexists : 1 ; $checkmessageexists = defined( $checkmessageexists ) ? $checkmessageexists : 1 ;
$expungeaftereach = defined( $expungeaftereach ) ? $expungeaftereach : 1 ;
print banner_imapsync(@argv_copy); print banner_imapsync(@argv_copy);
@ -1044,8 +1058,8 @@ foreach my $h1_fold (@h1_folders_all) {
if ( $foldersizes ) { if ( $foldersizes ) {
foldersizes( "Host1", $imap1, @h1_folders_wanted ) ; ( $h1_nb_msg_start, $h1_bytes_start ) = foldersizes( "Host1", $imap1, @h1_folders_wanted ) ;
foldersizes( "Host2", $imap2, @h2_folders_from_1_wanted ) ; ( $h2_nb_msg_start, $h2_bytes_start ) = foldersizes( "Host2", $imap2, @h2_folders_from_1_wanted ) ;
sleep( 2 ) ; sleep( 2 ) ;
} }
@ -1221,6 +1235,7 @@ FOLDER: foreach my $h1_fold (@h1_folders_wanted) {
$total_bytes_skipped += $h1_size; $total_bytes_skipped += $h1_size;
$nb_msg_skipped += 1; $nb_msg_skipped += 1;
$h1_nb_msg_noheader +=1; $h1_nb_msg_noheader +=1;
$h1_nb_msg_processed +=1 ;
} elsif(0 == $rc) { } elsif(0 == $rc) {
# duplicate # duplicate
push(@h1_msgs_duplicate, $m); push(@h1_msgs_duplicate, $m);
@ -1229,6 +1244,7 @@ FOLDER: foreach my $h1_fold (@h1_folders_wanted) {
$nb_msg_skipped += 1; $nb_msg_skipped += 1;
$h1_total_bytes_duplicate += $h1_size; $h1_total_bytes_duplicate += $h1_size;
$h1_nb_msg_duplicate += 1; $h1_nb_msg_duplicate += 1;
$h1_nb_msg_processed +=1 ;
} }
} }
my $h1_msgs_duplicate_nb = scalar( @h1_msgs_duplicate ) ; my $h1_msgs_duplicate_nb = scalar( @h1_msgs_duplicate ) ;
@ -1281,6 +1297,7 @@ FOLDER: foreach my $h1_fold (@h1_folders_wanted) {
= sort {$h2_hash{$a}{'m'} <=> $h2_hash{$b}{'m'}} keys(%h2_hash); = sort {$h2_hash{$a}{'m'} <=> $h2_hash{$b}{'m'}} keys(%h2_hash);
if ( 0 ) { if ( 0 ) {
# What the hell was this code written for?
# hashes, keys are uid, values are the internaldates in epoch (best format to compare dates) # hashes, keys are uid, values are the internaldates in epoch (best format to compare dates)
my %h1_epoch ; my %h1_epoch ;
my %h2_epoch ; my %h2_epoch ;
@ -1341,7 +1358,7 @@ FOLDER: foreach my $h1_fold (@h1_folders_wanted) {
$debug and print "Host2 uidnext: $h2_uidnext\n" ; $debug and print "Host2 uidnext: $h2_uidnext\n" ;
$h2_uidguess = $h2_uidnext ; $h2_uidguess = $h2_uidnext ;
MESS: foreach my $m_id (@h1_hash_keys_sorted_by_uid) { MESS: foreach my $m_id (@h1_hash_keys_sorted_by_uid) {
#print "h1_nb_msg_processed: $h1_nb_msg_processed\n" ;
my $h1_size = $h1_hash{$m_id}{'s'}; my $h1_size = $h1_hash{$m_id}{'s'};
my $h1_msg = $h1_hash{$m_id}{'m'}; my $h1_msg = $h1_hash{$m_id}{'m'};
my $h1_idate = $h1_hash{$m_id}{'D'}; my $h1_idate = $h1_hash{$m_id}{'D'};
@ -1360,6 +1377,8 @@ FOLDER: foreach my $h1_fold (@h1_folders_wanted) {
$debug and print "Host1 found msg $h1_fold/$h1_msg equals Host2 $h2_fold/$h2_msg\n" ; $debug and print "Host1 found msg $h1_fold/$h1_msg equals Host2 $h2_fold/$h2_msg\n" ;
$total_bytes_skipped += $h1_size ; $total_bytes_skipped += $h1_size ;
$nb_msg_skipped += 1 ; $nb_msg_skipped += 1 ;
$h1_nb_msg_processed +=1 ;
if ( $usecache ) { if ( $usecache ) {
$debugcache and print "touch $cache_dir/${h1_msg}_$h2_msg\n" ; $debugcache and print "touch $cache_dir/${h1_msg}_$h2_msg\n" ;
touch( "$cache_dir/${h1_msg}_$h2_msg" ) touch( "$cache_dir/${h1_msg}_$h2_msg" )
@ -1378,12 +1397,12 @@ FOLDER: foreach my $h1_fold (@h1_folders_wanted) {
"Host1 size msg $h1_fold/$h1_msg = $h1_size <> $h2_size = Host2 $h2_fold/$h2_msg\n"; "Host1 size msg $h1_fold/$h1_msg = $h1_size <> $h2_size = Host2 $h2_fold/$h2_msg\n";
if( $delete ) { if( $delete ) {
my $expunge_message = '' ; my $expunge_message = '' ;
$expunge_message = "and expunged" if ( $expunge or $expunge1 ) ; $expunge_message = "and expunged" if ( $expungeaftereach and ( $expunge or $expunge1 ) ) ;
print "Host1 msg $h1_fold/$h1_msg marked deleted $expunge_message $dry_message\n" ; print "Host1 msg $h1_fold/$h1_msg marked deleted $expunge_message $dry_message\n" ;
unless( $dry ) { unless( $dry ) {
$imap1->delete_message( $h1_msg ) ; $imap1->delete_message( $h1_msg ) ;
$h1_nb_msg_deleted += 1 ; $h1_nb_msg_deleted += 1 ;
$imap1->expunge() if ( $expunge or $expunge1 ) ; $imap1->expunge() if ( $expungeaftereach and ( $expunge or $expunge1 ) ) ;
} }
} }
@ -1398,6 +1417,7 @@ FOLDER: foreach my $h1_fold (@h1_folders_wanted) {
my $h1_size = $h1_fir_ref->{ $h1_msg }->{ 'RFC822.SIZE' } || 0 ; my $h1_size = $h1_fir_ref->{ $h1_msg }->{ 'RFC822.SIZE' } || 0 ;
$total_bytes_skipped += $h1_size; $total_bytes_skipped += $h1_size;
$nb_msg_skipped += 1; $nb_msg_skipped += 1;
$h1_nb_msg_processed +=1 ;
} }
#print "Messages by uid: ", map { "$_ " } keys %h1_msgs_copy_by_uid, "\n" ; #print "Messages by uid: ", map { "$_ " } keys %h1_msgs_copy_by_uid, "\n" ;
@ -1903,8 +1923,8 @@ sub banner_imapsync {
my @argv_copy = @_; my @argv_copy = @_;
my $banner_imapsync = join("", my $banner_imapsync = join("",
'$RCSfile: imapsync,v $ ', '$RCSfile: imapsync,v $ ',
'$Revision: 1.504 $ ', '$Revision: 1.508 $ ',
'$Date: 2012/08/28 13:10:26 $ ', '$Date: 2012/09/10 21:10:13 $ ',
"\n",localhost_info(), "\n", "\n",localhost_info(), "\n",
"Command line used:\n", "Command line used:\n",
"$0 ", command_line_nopassword(@argv_copy), "\n", "$0 ", command_line_nopassword(@argv_copy), "\n",
@ -2352,10 +2372,11 @@ sub foldersizes {
$total_size += $stot ; $total_size += $stot ;
$total_nb += $nb_msgs ; $total_nb += $nb_msgs ;
} }
printf ( "Nb messages: %11s messages\n", $total_nb ) ; printf ( "%s Nb messages: %11s messages\n", $side, $total_nb ) ;
printf ( "Total size: %11s bytes (%s)\n", $total_size, bytes_display_string( $total_size ) ) ; printf ( "%s Total size: %11s bytes (%s)\n", $side, $total_size, bytes_display_string( $total_size ) ) ;
printf ( "Biggest message: %11s bytes (%s)\n", $biggest, bytes_display_string( $biggest ) ) ; printf ( "%s Biggest message: %11s bytes (%s)\n", $side, $biggest, bytes_display_string( $biggest ) ) ;
printf ( "Time spent: %11.1f seconds\n", timenext( ) ) ; printf ( "%s Time spent: %11.1f seconds\n", $side, timenext( ) ) ;
return( $total_nb, $total_size ) ;
} }
sub timenext { sub timenext {
@ -2735,13 +2756,22 @@ sub copy_message {
my $h1_flags = $h1_fir_ref->{$h1_msg}->{"FLAGS"} || '' ; my $h1_flags = $h1_fir_ref->{$h1_msg}->{"FLAGS"} || '' ;
my $h1_idate = $h1_fir_ref->{$h1_msg}->{"INTERNALDATE"} || '' ; my $h1_idate = $h1_fir_ref->{$h1_msg}->{"INTERNALDATE"} || '' ;
return() if size_filtered( $h1_size, $h1_msg, $h1_fold, $h2_fold ) ;
if (size_filtered( $h1_size, $h1_msg, $h1_fold, $h2_fold ) ) {
$h1_nb_msg_processed +=1 ;
return( ) ;
}
my $string; my $string;
do { print "SLEEP 5\n" and sleep 5 ; } if ( $debugsleep ) ; do { print "SLEEP 5\n" and sleep 5 ; } if ( $debugsleep ) ;
print "- msg $h1_fold/$h1_msg S[$h1_size] F[$h1_flags] I[$h1_idate] has RFC822.SIZE null!\n" if ( ! $h1_size ) ; print "- msg $h1_fold/$h1_msg S[$h1_size] F[$h1_flags] I[$h1_idate] has RFC822.SIZE null!\n" if ( ! $h1_size ) ;
return( ) if ( $checkmessageexists and not message_exists( $imap1, $h1_msg ) ) ;
if ( $checkmessageexists and not message_exists( $imap1, $h1_msg ) ) {
$h1_nb_msg_processed +=1 ;
return( ) ;
}
$string = $imap1->message_string($h1_msg); $string = $imap1->message_string($h1_msg);
@ -2754,6 +2784,7 @@ sub copy_message {
$nb_errors++ ; $nb_errors++ ;
$total_bytes_error += $h1_size if ( $h1_size ) ; $total_bytes_error += $h1_size if ( $h1_size ) ;
#relogin1( ) if ( $relogin1 ) ; #relogin1( ) if ( $relogin1 ) ;
$h1_nb_msg_processed +=1 ;
return( ) ; return( ) ;
} }
@ -2807,6 +2838,7 @@ sub copy_message {
$imap2->LastError, "\n"; $imap2->LastError, "\n";
$nb_errors++; $nb_errors++;
$total_bytes_error += $h1_size; $total_bytes_error += $h1_size;
$h1_nb_msg_processed +=1 ;
return( ) ; return( ) ;
} }
else{ else{
@ -2819,12 +2851,15 @@ sub copy_message {
$h2_uidguess += 1 ; $h2_uidguess += 1 ;
$total_bytes_transferred += $h1_size ; $total_bytes_transferred += $h1_size ;
$nb_msg_transferred += 1 ; $nb_msg_transferred += 1 ;
$h1_nb_msg_processed +=1 ;
my $time_spent = timesince( $begin_transfer_time ) ; my $time_spent = timesince( $begin_transfer_time ) ;
my $rate = bytes_display_string( $total_bytes_transferred / $time_spent ) ; my $rate = bytes_display_string( $total_bytes_transferred / $time_spent ) ;
my $eta = eta( $time_spent, $h1_nb_msg_processed, $h1_nb_msg_start, $nb_msg_transferred ) ;
#my $eta = eta( $time_spent, $nb_msg_transferred, $h1_nb_msg_start ) ;
printf( "msg %s/%-19s copied to %s/%-10s %.2f msgs/s %s/s\n", printf( "msg %s/%-19s copied to %s/%-10s %.2f msgs/s %s/s %s\n",
$h1_fold, "$h1_msg {$string_len}", $h2_fold, $new_id, $nb_msg_transferred/$time_spent, $rate ); $h1_fold, "$h1_msg {$string_len}", $h2_fold, $new_id, $nb_msg_transferred/$time_spent, $rate, $eta );
if ( $usecache and $cacheaftercopy and $new_id =~ m{^\d+$} ) { if ( $usecache and $cacheaftercopy and $new_id =~ m{^\d+$} ) {
$debugcache and print "touch $cache_dir/${h1_msg}_$new_id\n" ; $debugcache and print "touch $cache_dir/${h1_msg}_$new_id\n" ;
@ -2844,8 +2879,39 @@ sub copy_message {
} }
else{ else{
$nb_msg_skipped_dry_mode += 1; $nb_msg_skipped_dry_mode += 1;
$h1_nb_msg_processed +=1 ;
} }
return( ); }
sub eta {
return( '' ) if not $foldersizes ;
my( $time_spent, $h1_nb_msg_processed, $h1_nb_msg_start, $nb_msg_transferred ) = @_ ;
my $time_remaining = time_remaining( @_ ) ;
my $nb_msg_remaining = $h1_nb_msg_start - $h1_nb_msg_processed ;
my $eta_date = localtime( time + $time_remaining ) ;
return( sprintf( "ETA: %s %1.0f s %s msgs left", $eta_date, $time_remaining, $nb_msg_remaining ) ) ;
}
sub time_remaining {
my( $time_spent, $h1_nb_msg_processed, $h1_nb_msg_start, $nb_msg_transferred ) = @_ ;
my $time_remaining = ( $time_spent / $nb_msg_transferred ) * ( $h1_nb_msg_start - $h1_nb_msg_processed ) ;
return( $time_remaining ) ;
}
sub tests_time_remaining {
ok( 1 == time_remaining( 1, 1, 2, 1 ), "time_remaining: 1, 1, 2, 1 -> 1") ;
ok( 1 == time_remaining( 9, 9, 10, 9 ), "time_remaining: 9, 9, 10, 9 -> 1") ;
ok( 9 == time_remaining( 1, 1, 10, 1 ), "time_remaining: 1, 1, 10, 1 -> 1") ;
} }
@ -3274,20 +3340,27 @@ sub touch {
return( ! $failures ); return( ! $failures );
} }
sub tests_cache_folder {
ok( '/path/fold1/fold2' eq cache_folder( '/path', 'fold1', 'fold2'), 'cache_folder: /path, fold1, fold2 -> /path/fold1/fold2' ) ;
ok( '/pa_th/fold1/fold2' eq cache_folder( '/pa*th', 'fold1', 'fold2'), 'cache_folder: /pa*th, fold1, fold2 -> /path/fold1/fold2' ) ;
ok( '/_p_a__th/fol_d1/fold2' eq cache_folder( '/>p<a|*th', 'fol*d1', 'fold2'), 'cache_folder: />p<a|*th, fol*d1, fold2 -> /path/fol_d1/fold2' ) ;
}
sub cache_folder { sub cache_folder {
my( $cache_dir, $h1_fold, $h2_fold ) = @_ ; my( $cache_dir, $h1_fold, $h2_fold ) = @_ ;
#print "sep1 $h1_sep sep2 $h2_sep\n";
my $sep1 = $h1_sep || '/'; my $sep1 = $h1_sep || '/';
my $sep2 = $h2_sep || '/'; my $sep2 = $h2_sep || '/';
#print "$cache_dir h1_fold $h1_fold sep1 $sep1 h2_fold $h2_fold sep2 $sep2\n";
$h1_fold = convert_sep_to_slash( $h1_fold, $sep1 ) ; $h1_fold = convert_sep_to_slash( $h1_fold, $sep1 ) ;
$h2_fold = convert_sep_to_slash( $h2_fold, $sep2 ) ; $h2_fold = convert_sep_to_slash( $h2_fold, $sep2 ) ;
$h1_fold = filter_forbidden_characters( $h1_fold ) ; my $cache_folder = "$cache_dir/$h1_fold/$h2_fold" ;
$h2_fold = filter_forbidden_characters( $h2_fold ) ; $cache_folder = filter_forbidden_characters( $cache_folder ) ;
#print "cache_folder [$cache_folder]\n" ;
return( "$cache_dir/$h1_fold/$h2_fold" ) ; return( $cache_folder ) ;
} }
sub filter_forbidden_characters { sub filter_forbidden_characters {
@ -3606,6 +3679,7 @@ sub get_options {
"exitwhenover=i" => \$exitwhenover, "exitwhenover=i" => \$exitwhenover,
"checkselectable!" => \$checkselectable, "checkselectable!" => \$checkselectable,
"checkmessageexists!" => \$checkmessageexists, "checkmessageexists!" => \$checkmessageexists,
"expungeaftereach!" => \$expungeaftereach,
); );
$debug and print "get options: [$opt_ret]\n"; $debug and print "get options: [$opt_ret]\n";
@ -3795,7 +3869,7 @@ sub check_last_release {
} }
sub imapsync_version { sub imapsync_version {
my $rcs = '$Id: imapsync,v 1.504 2012/08/28 13:10:26 gilles Exp gilles $ '; my $rcs = '$Id: imapsync,v 1.508 2012/09/10 21:10:13 gilles Exp gilles $ ';
$rcs =~ m/,v (\d+\.\d+)/; $rcs =~ m/,v (\d+\.\d+)/;
my $VERSION = ($1) ? $1: "UNKNOWN"; my $VERSION = ($1) ? $1: "UNKNOWN";
return($VERSION); return($VERSION);
@ -4594,7 +4668,7 @@ sub tests_debug {
SKIP: { SKIP: {
skip "No test in normal run" if ( not $tests_debug ); skip "No test in normal run" if ( not $tests_debug );
tests_cache_dir_fix( ) ; tests_time_remaining( ) ;
} }
} }
@ -4633,6 +4707,7 @@ sub tests {
tests_add_header( ) ; tests_add_header( ) ;
tests_cache_dir_fix( ) ; tests_cache_dir_fix( ) ;
tests_filter_forbidden_characters( ) ; tests_filter_forbidden_characters( ) ;
tests_cache_folder( ) ;
} }
} }

View file

@ -5,7 +5,7 @@
<title>Imapsync: an IMAP migration tool ( release <!--#exec cmd="cat ./VERSION"--> )</title> <title>Imapsync: an IMAP migration tool ( release <!--#exec cmd="cat ./VERSION"--> )</title>
<meta name="generator" content="Bluefish 1.0.7"/> <meta name="generator" content="Bluefish 1.0.7"/>
<meta name="author" content="Gilles LAMIRAL"/> <meta name="author" content="Gilles LAMIRAL"/>
<meta name="date" content="2012-08-29T12:23:32+0200"/> <meta name="date" content="2012-09-12T00:06:47+0200"/>
<meta name="copyright" content="None"/> <meta name="copyright" content="None"/>
<meta name="keywords" content="imap, transfert, migration"/> <meta name="keywords" content="imap, transfert, migration"/>
<meta name="description" content="imap migration tool"/> <meta name="description" content="imap migration tool"/>
@ -95,7 +95,7 @@ total is 93 millions for 2011</li>
<p>New features or bugfixes since previous releases:</p> <p>New features or bugfixes since previous releases:</p>
<!-- <ul> <!-- <ul>
<li><b>1.504</b></li> <li><b>1.508</b></li>
<li><b>Enhancement</b>: </li> <li><b>Enhancement</b>: </li>
<li><b>Enhancement</b>: </li> <li><b>Enhancement</b>: </li>
<li><b>Enhancement</b>: </li> <li><b>Enhancement</b>: </li>
@ -111,9 +111,18 @@ total is 93 millions for 2011</li>
</ul> </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>
</ul>
<ul> <ul>
<li><b>1.504</b></li> <li><b>1.504</b></li>
<li><b>Enhancement</b>: Added option <b>--nocheckmessageexists</b> to <b>speed up</b> with <b>Tobbit imap server</b> as host1.</li> <li><b>Enhancement</b>: Added option <b>--nocheckmessageexists</b> to <b>speed up</b> with <b>Tobit imap server</b> as host1.</li>
<li><b>Usability</b>: Added <b>transfer rate</b> and number of messages rate <b>after each copy</b>.</li> <li><b>Usability</b>: Added <b>transfer rate</b> and number of messages rate <b>after each copy</b>.</li>
<li><b>Usability</b>: Use Time::HiRes time to get time with better precesion than the second.</li> <li><b>Usability</b>: Use Time::HiRes time to get time with better precesion than the second.</li>
<li><b>Bug fix</b>: Convert characters <kbd>*|?:"&lt;&gt;</kbd> to <kbd>_</kbd> in cache paths because they are forbidden on Windows paths.</li> <li><b>Bug fix</b>: Convert characters <kbd>*|?:"&lt;&gt;</kbd> to <kbd>_</kbd> in cache paths because they are forbidden on Windows paths.</li>
@ -422,71 +431,85 @@ Don't hesitate to have a try, I will help you and make efforts to switch them to
[host1] means "source server" and [host2] means "destination server": [host1] means "source server" and [host2] means "destination server":
</p> </p>
<!--
(<a href=""></a>)
-->
<ul> <ul>
<li>1und1 H mimap1 84498 [host1]</li> <li>1und1 H mimap1 84498 [host1] (<a href="http://www.1und1.de/">http://www.1und1.de/</a>)</li>
<li>a1.net imap.a1.net IMAP4 Ready [host1] </li> <li>a1.net imap.a1.net IMAP4 Ready [host1] </li>
<li>Archiveopteryx 2.03, 2.04, 2.09, 2.10 [host2], 3.0.0 [host2] <li>Archiveopteryx 2.03, 2.04, 2.09, 2.10 [host2], 3.0.0 [host2]
(OSL 3.0) http://www.archiveopteryx.org/</li> (OSL 3.0) (<a href="http://www.archiveopteryx.org/">http://www.archiveopteryx.org/</a>)</li>
<li>Axigen Mail Server Version 8.0.0</li> <li>Axigen Mail Server Version 8.0.0 (<a href="http://www.axigen.com/">http://www.axigen.com/</a>)</li>
<li>BincImap 1.2.3 (GPL) (http://www.bincimap.org/)</li> <li>BincImap 1.2.3 (GPL) (<a href="http://www.bincimap.org/">http://www.bincimap.org/</a>)</li>
<li>CommuniGatePro server (Redhat 8.0) (Solaris), CommuniGate Pro 5.2.17[host2] (CentOS 5.4)</li> <li>CommuniGatePro server (Redhat 8.0) (Solaris), CommuniGate Pro 5.2.17[host2] (CentOS 5.4)
(<a href="http://www.communigate.com/">http://www.communigate.com/</a>) </li>
<li>Courier IMAP 1.5.1, 2.2.0, 2.1.1, 2.2.1, 3.0.8, 3.0.3, 4.1.1 (GPL) <li>Courier IMAP 1.5.1, 2.2.0, 2.1.1, 2.2.1, 3.0.8, 3.0.3, 4.1.1 (GPL)
(http://www.courier-mta.org/)</li> (<a href="http://www.courier-mta.org/imap/">http://www.courier-mta.org/imap/</a>) </li>
<li>Critical Path (7.0.020)</li> <li>Critical Path (7.0.020) (<a href=""></a>) </li>
<li>Cyrus IMAP 1.5, 1.6, <li>Cyrus IMAP 1.5, 1.6,
2.1, 2.1.15, 2.1.16, 2.1.18 2.1, 2.1.15, 2.1.16, 2.1.18
2.2.1, 2.2.2-BETA, 2.2.3, 2.2.6, 2.2.10, 2.2.12, 2.2.13, 2.2.1, 2.2.2-BETA, 2.2.3, 2.2.6, 2.2.10, 2.2.12, 2.2.13,
2.3-alpha (OSI Approved), 2.3.1, 2.3.7, 2.3.16 2.3-alpha (OSI Approved), 2.3.1, 2.3.7, 2.3.16
(http://asg.web.cmu.edu/cyrus/) (<a href="http://cyrusimap.web.cmu.edu/">http://cyrusimap.web.cmu.edu/</a>)
</li> </li>
<li>David Tobit V8.</li> <li>David Tobit V8. (<a href="http://www.tobit.com/">http://www.tobit.com/</a>) </li>
<li>DBMail 1.2.1, 2.0.4, 2.0.9, 2.2rc1 (GPL) (http://www.dbmail.org/). <li>DBMail 1.2.1, 2.0.4, 2.0.9, 2.2rc1 (GPL).
2.0.7 seems buggy.</li> 2.0.7 seems buggy. (<a href="http://www.dbmail.org/">http://www.dbmail.org/</a>) </li>
<li>Deerfield VisNetic MailServer 5.8.6 [host1]</li> <li>Deerfield VisNetic MailServer 5.8.6 [host1]
<li>dkimap4 [host1]</li> (<a href="http://www.deerfield.net/products/visnetic-mailserver/">http://www.deerfield.net/products/visnetic-mailserver/</a>) </li>
<li>Domino (Notes) 4.61[host1], 6.5, 5.0.6, 5.0.7, 7.0.2, 6.0.2CF1, 7.0.1[host1], 8.0.1[host1]</li> <li>dkimap4 [host1] (<a href=""></a>) </li>
<li>Domino (Notes) 4.61[host1], 6.5, 5.0.6, 5.0.7, 7.0.2, 6.0.2CF1, 7.0.1[host1], 8.0.1[host1]
(<a href="http://www-01.ibm.com/software/lotus/products/notes/">http://www-01.ibm.com/software/lotus/products/notes/</a>) </li>
<li><b>Dovecot</b> 0.99.10.4, 0.99.14, 0.99.14-8.fc4, 1.0-0.beta2.7, <li><b>Dovecot</b> 0.99.10.4, 0.99.14, 0.99.14-8.fc4, 1.0-0.beta2.7,
1.0.0 [dest/source] (LGPL) (http://www.dovecot.org/)</li> 1.0.0 [dest/source] (LGPL) (http://www.dovecot.org/) (<a href="http://www.dovecot.org/">http://www.dovecot.org/</a>) </li>
<li>Eudora WorldMail v2</li> <li>Eudora WorldMail v2 (<a href="http://www.eudora.com/worldmail/">http://www.eudora.com/worldmail/</a>) </li>
<li><b>Gimap</b> (<b>Gmail</b> imap) [host1] [host2]</li> <li><b>Gimap</b> (<b>Gmail</b> imap) [host1] [host2] (<a href="http://mail.google.com/">http://mail.google.com/</a>) </li>
<li>GMX IMAP4 StreamProxy.</li> <li>GMX IMAP4 StreamProxy. (<a href="http://www.gmx.com/">http://www.gmx.com/</a>) </li>
<li>Godaddy IMAP (since Godaddy runs Courier)</li> <li>Godaddy IMAP (since Godaddy runs Courier) (<a href="http://www.godaddy.com/">http://www.godaddy.com/</a>) </li>
<li>Groupwise IMAP (Novell) 6.x and 7.0. Buggy so see the FAQ.</li> <li>Groupwise IMAP (Novell) 6.x and 7.0. Buggy so see the FAQ.
<li>hMailServer 5.3.3 [host2], 4.4.1 [host1], HMAILSERVER 5.3.2-B1769 on windows 2003 [hsot2]</li> (<a href="http://www.novell.com/products/groupwise/">http://www.novell.com/products/groupwise/</a>) </li>
<li>iPlanet Messaging server 4.15, 5.1, 5.2</li> <li>hMailServer 5.3.3 [host2], 4.4.1 [host1], HMAILSERVER 5.3.2-B1769 on windows 2003 [hsot2]
<li>IMail 7.15 (Ipswitch/Win2003), 8.12, 11.03 [host1]</li> (<a href="http://www.hmailserver.com/">http://www.hmailserver.com/</a>) </li>
<li>Kerio 7.2.0P1 [host1]</li> <li>iPlanet Messaging server 4.15, 5.1, 5.2
<li><b>MailEnable</b> 4.23 [host1][host2], 4.26 [host1][host2], 5 [host1]</li> (<a href="http://en.wikipedia.org/wiki/Oracle_Communications_Messaging_Server">http://en.wikipedia.org/wiki/Oracle_Communications_Messaging_Server</a>) </li>
<li>MDaemon 7.0.1, 8.0.2, 8.1, 9.5.4 (Windows server 2003 R2 platform), 12 [host2], 12.0.3 [host1], 12.5.5 [host1]</li> <li>IMail 7.15 (Ipswitch/Win2003), 8.12, 11.03 [host1] (<a href="http://www.imailserver.com/">http://www.imailserver.com/</a>) </li>
<li>Mercury 4.1 (Windows server 2000 platform)</li> <li>Kerio 7.2.0P1 [host1] (<a href="http://www.kerio.com/">http://www.kerio.com/</a>) </li>
<li><b>MailEnable</b> 4.23 [host1][host2], 4.26 [host1][host2], 5 [host1]
(<a href="http://www.mailenable.com/">http://www.mailenable.com/</a>) </li>
<li>MDaemon 7.0.1, 8.0.2, 8.1, 9.5.4 (Windows server 2003 R2 platform), 12 [host2], 12.0.3 [host1], 12.5.5 [host1]
(<a href="http://www.altn.com/">http://www.altn.com/</a>) </li>
<li>Mercury 4.1 (Windows server 2000 platform) (<a href="http://www.pmail.com/">http://www.pmail.com/</a>) </li>
<li><b>Microsoft Exchange Server</b> 5.5, 6.0.6249.0[host1], 6.0.6487.0[host1], <li><b>Microsoft Exchange Server</b> 5.5, 6.0.6249.0[host1], 6.0.6487.0[host1],
6.5.7638.1 [host2], 6.5 [host1], Exchange 2007 SP1 (with Update Rollup 2), 6.5.7638.1 [host2], 6.5 [host1], Exchange 2007 SP1 (with Update Rollup 2),
Exchange2007-EP-SP2, Exchange2007-EP-SP2,
Exchange 2010 RTM (Release to Manufacturing) [host2], Exchange 2010 RTM (Release to Manufacturing) [host2],
Exchange 2010 SP1 RU2 [host2] Exchange 2010 SP1 RU2 [host2]
(<a href="http://www.microsoft.com/exchange/">http://www.microsoft.com/exchange/</a>)
</li> </li>
<li>Mirapoint server 4.1.9-GA [host1]</li> <li>Mirapoint server 4.1.9-GA [host1] (<a href="http://www.mirapoint.com/">http://www.mirapoint.com/</a>) </li>
<li>Netscape Mail Server 3.6 (Wintel) </li> <li>Netscape Mail Server 3.6 (Wintel) </li>
<li>Netscape Messaging Server 4.15 Patch 7 </li> <li>Netscape Messaging Server 4.15 Patch 7 </li>
<li>OpenMail IMAP server B.07.00.k0 </li> <li>OpenMail IMAP server B.07.00.k0 </li>
<li>OpenWave</li> <li>OpenWave (<a href="http://www.openwave.com/">http://www.openwave.com/</a>) </li>
<li>Oracle Beehive [host1]</li> <li>Oracle Beehive [host1]
<li>Qualcomm Worldmail (NT)</li> (<a href="http://www.oracle.com/technetwork/middleware/beehive/">http://www.oracle.com/technetwork/middleware/beehive/</a>) </li>
<li>Rockliffe Mailsite 5.3.11, 4.5.6</li> <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>Samsung Contact IMAP server 8.5.0 </li>
<li>Scalix v10.1, 10.0.1.3, 11.0.0.431</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>SmarterMail, Smarter Mail 5.0 Enterprise, Smarter Mail 5.5 [host1].</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)</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</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>
<li>Surgemail 3.6f5-5</li> <li>Surgemail 3.6f5-5 (<a href="http://netwinsite.com/surgemail/">http://netwinsite.com/surgemail/</a>) </li>
<li>UW-imap servers (imap-2000b) rijkkramer IMAP4rev1 2000.287 <li>UW-imap servers (imap-2000b) rijkkramer IMAP4rev1 2000.287
(RedHat uses UW like 2003.338rh), v12.264 Solaris 5.7 (OSI Approved) (RedHat uses UW like 2003.338rh), v12.264 Solaris 5.7 (OSI Approved)
(http://www.washington.edu/imap/)</li> (<a href="http://www.washington.edu/imap/">http://www.washington.edu/imap/</a>) </li>
<li>UW - QMail v2.1</li> <li>VMS, Imap part of TCP/IP suite of VMS 7.3.2 (<a href="http://h71000.www7.hp.com/openvms/">http://h71000.www7.hp.com/openvms/</a>) </li>
<li>VMS, Imap part of TCP/IP suite of VMS 7.3.2</li> <li><b>Yahoo</b> [host1] (<a href="http://www.yahoo.com/">http://www.yahoo.com/</a>) </li>
<li><b>Yahoo</b> [host1]</li>
<li><b>Zimbra-IMAP</b> 3.0.1 GA 160, 3.1.0 Build 279, 4.0.5, 4.5.2, 4.5.6, <li><b>Zimbra-IMAP</b> 3.0.1 GA 160, 3.1.0 Build 279, 4.0.5, 4.5.2, 4.5.6,
Zimbra 5.0.24_GA_3356.RHEL4 [host1], 5.5, 6.x</li> Zimbra 5.0.24_GA_3356.RHEL4 [host1], 5.5, 6.x
(<a href="http://www.zimbra.com/">http://www.zimbra.com/</a>) </li>
</ul> </ul>
<h2><a id="similar"></a>Similar softwares</h2> <h2><a id="similar"></a>Similar softwares</h2>
@ -553,7 +576,7 @@ alt="Viewable With Any Browser" />
<!--#config timefmt="%D" --> <!--#config timefmt="%D" -->
<!--#config timefmt="%A %B %d, %Y" --> <!--#config timefmt="%A %B %d, %Y" -->
<b>This document last modified on <!--#echo var="LAST_MODIFIED" --></b> <b>This document last modified on <!--#echo var="LAST_MODIFIED" --></b>
($Id: index.shtml,v 1.129 2012/08/29 10:25:29 gilles Exp gilles $) ($Id: index.shtml,v 1.131 2012/09/11 22:07:18 gilles Exp gilles $)
</p> </p>
</body> </body>

View file

@ -1,9 +1,9 @@
#!/bin/sh #!/bin/sh
# $Id: tests.sh,v 1.200 2012/08/28 13:11:30 gilles Exp gilles $ # $Id: tests.sh,v 1.201 2012/09/10 21:12:35 gilles Exp gilles $
# Example 1: # Example 1:
# CMD_PERL='perl -I./Mail-IMAPClient-3.31/lib' sh -x tests.sh # CMD_PERL='perl -I./Mail-IMAPClient-3.32/lib' sh -x tests.sh
# Example 2: # Example 2:
# To select which Mail-IMAPClient within arguments: # To select which Mail-IMAPClient within arguments:
@ -23,7 +23,7 @@ echo HOST2=$HOST2
# few debugging tests use: # few debugging tests use:
CMD_PERL_2xx='perl -I./W/Mail-IMAPClient-2.2.9' CMD_PERL_2xx='perl -I./W/Mail-IMAPClient-2.2.9'
CMD_PERL_3xx='perl -I./W/Mail-IMAPClient-3.31/lib' CMD_PERL_3xx='perl -I./W/Mail-IMAPClient-3.32/lib'
CMD_PERL=${CMD_PERL:-$CMD_PERL_3xx} CMD_PERL=${CMD_PERL:-$CMD_PERL_3xx}
@ -1591,6 +1591,28 @@ ll_delete2() {
--delete2 --expunge2 --delete2 --expunge2
} }
ll_delete2_reverse() {
$CMD_PERL ./imapsync \
--host1 $HOST1 --user1 titi \
--passfile1 ../../var/pass/secret.titi \
--host2 $HOST2 --user2 tata \
--passfile2 ../../var/pass/secret.tata \
--folder INBOX \
--delete2 --expunge2
}
ll_delete_reverse() {
$CMD_PERL ./imapsync \
--host1 $HOST1 --user1 titi \
--passfile1 ../../var/pass/secret.titi \
--host2 $HOST2 --user2 tata \
--passfile2 ../../var/pass/secret.tata \
--folder INBOX \
--delete --minage 100 --maxage 300 --noexpungeaftereach
}
ll_delete2_minage() { ll_delete2_minage() {
can_send && sendtestmessage titi can_send && sendtestmessage titi
$CMD_PERL ./imapsync \ $CMD_PERL ./imapsync \